概要
クロスデバイスパラメータについて
Criteo V3タグ内にクロスデバイスのパラメータを実装することで、強力なCriteoショッパーグラフを利用できるようになります。Criteoショッパーグラフを利用するメリットには、以下のようなものがあります。
- お客様の店舗を利用する、あるいは数万ものプレミアムパブリッシャーのサイトを閲覧する新規および既存顧客を対象に、オムニチャネルのショッピングジャーニーを統合します。
- 120以上のショッピングシグナルから高粒度の膨大な買物客データを収集して、お客様のカタログの中で買物客が興味・関心を持っている商品を特定します。
- 決定論的手法に基づいて構築された買物客のIDに、追加コストなしでセキュアにアクセスできるため、これらをマーケティングや測定・分析への取り組みに役立てることができます。
- データの透明性、プライバシー、セキュリティを高いレベルで維持します。
Criteoショッパーグラフの使用例:例えば、顧客がモバイルデバイスでお客様のWebサイトの商品を閲覧しているとします。Criteoショッパーグラフは、その後で顧客がデスクトップデバイスを使用している時にも関連性の高い広告を表示できるようにします。
Criteoショッパーグラフの仕組み
ユーザのEメールアドレスは、クロスデバイスのパラメータ内で受け渡しを行います。個人識別可能な情報(PII)を保護するために、Eメールアドレスはすべて(SHA-256アルゴリズムを使って)ハッシュ化されてからCriteoのサーバーに保存されます。Criteoはハッシュ値を使い、ユーザの各デバイスを横断してマッチングを行います。
クロスデバイスパラメータの実装方法
クロスデバイスパラメータは、お客様のWebサイトの訪問者のEメールアドレスを匿名化して受け渡す小さなコードの断片です。クライアントへの柔軟性を最大限に高めるため、Criteoはユーザのプレーンテキストまたはハッシュ化されたEメールアドレスを受け取ります。プレーンテキストで送られた場合は、Criteo側でEメールをハッシュ化します。
プレーンテキストのemailまたはMD5でハッシュ化されたemailを渡す場合は、setEmail を使用してください。
ハッシュ化される前あるいはプレーンテキストとしてタグに代入される時に全てのメールアドレスは以下のようになっている必要があります。
- トリム化されている(メールアドレスの前後のスペースがすべて削除されている)
- 小文字に変換されている。
- UTF-8にエンコードされている。
クロスデバイスのパラメータ
(MD5アルゴリズムを使用して)専用の関数によりあらかじめハッシュ化されたemailアドレスを送信することを推奨します。ここにあるのは setEmail で送信されるMD5でハッシュ化されたemailの一例です。
{ event: "setEmail", email: "b58996c504c5638798eb6b511e6f49af" },
ハッシュ化されていないメールアドレスが代入された場合、Criteoのデータベースに保存される前に自動的にユーザのメールアドレスをハッシュ化します。ここではsetEmaileventで送られるプレーンテキストのメールアドレスの一例です。
{ event: "setEmail", email: "user@example.com" },
ハッシュ化されていないまたはハッシュ化された電子メールアドレスのいずれかを渡すことができない場合は、単に当社に空の文字列を送ってください。
{ event: "setEmail", email: "" },
ハッシュ化機能
ユーザのEメールアドレスをCriteoが受け取る前にハッシュ化している場合には、以下のいずれかの機能で適切な暗号化を行うことができます。
PHPを使用するハッシュ化機能
$source_address = "uSèr@example.Com ";
$processed_address = strtolower($source_address); //convert address to lower case
$processed_address = trim($processed_address); //trimming leading and trailing spaces
$processed_address = mb_convert_encoding($processed_address, "UTF-8", "ISO-8859-1"); //conversion from ISO-8859-1 to UTF-8 (replace "ISO-8859-1" with the source encoding of your string)
$processed_address = md5($processed_address); //hash address with MD5 algorithm
echo "Source e-mail: ".$source_address."| Hashed e-mail: ".$processed_address;
C# を使用するハッシュ化機能
using System;
using System.Collections.Generic; using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace Sample_EmailHashing_code
{
public class CriteoHashedEmailFormatter
{
private static MD5 _md5;
private static MD5 Md5
{
get { return _md5 ?? (_md5 = MD5.Create()); }
}
private static string Md5Encode(string sourceString)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(sourceString);
byte[] hash = Md5.ComputeHash(inputBytes);
var sb = new StringBuilder(32);
foreach (byte b in hash)
sb.Append(b.ToString("x2"));
return sb.ToString();
}
public static string HashEmail(string sourceEmail)
{
String processedEmail;
processedEmail = sourceEmail.ToLowerInvariant(); //conversion to lower case
processedEmail = processedEmail.Trim(); //trimming leading and trailing spaces
//conversion to UTF-8 and hashing with MD5
processedEmail = Md5Encode(processedEmail);
return processedEmail;
}
}
class SampleEmailHashing
{
static void Main(string[] args)
{
String sourceEmail = " uSèr@example.Com ";
String processedEmail =
CriteoHashedEmailFormatter.HashEmail(sourceEmail);
Console.WriteLine(processedEmail);
Console.ReadKey();
}
}
}
PHPを使用するハッシュ化機能
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SampleEmailHashing {
public static void main(String[] args) {
String sourceEmail = new String(" uSèr@example.Com ");
String processedEmail = FormatMail(sourceEmail);
System.out.println(processedEmail);
}
//Method to format the source Email, converting to lower case and removing spaces private static String FormatMail(String mail) {
String newMail = new String(mail);
// conversion to lower case characters
newMail = newMail.toLowerCase();
//remove empty spaces
newMail = newMail.trim();
newMail = md5Java(newMail);
return newMail;
}
//Method to encrypt email address using MD5
public static String md5Java(String message) { String digest = null; try {
//conversion to UTF-8 and hashing with MD5 MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(message.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder(2 * hash.length);
for (byte b : hash) {
sb.append(String.format("%02x", b & 0xff));
}
digest = sb.toString();
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
} return digest;
}
}
Perlを使用するハッシュ化機能
#!/usr/bin/perl
use strict;
use warnings;
use Digest::MD5 qw(md5 md5_hex);
use Encode;
my $original_email = qw/ uSèr@example.Com /;
my $processed_email = lc($original_email);
$processed_email =~ s/^\s+//;
$processed_email =~ s/\s+$//;
$processed_email = encode_utf8($processed_email);
$processed_email = md5_hex($processed_email);
print "Original email:\t$original_email\n";
print "Hashed email:\t$processed_email \n";
JavaScriptを使用してハッシュ化する関数
function utf8_encode(argString) { if (argString === null || typeof argString === 'undefined') { return ''; } var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n"); var utftext = '', start, end, stringl = 0; start = end = 0; stringl = string.length; for (var n = 0; n < stringl; n++) { var c1 = string.charCodeAt(n); var enc = null; if (c1 < 128) { end++; } else if (c1 > 127 && c1 < 2048) { enc = String.fromCharCode( (c1 >> 6) | 192, (c1 & 63) | 128 ); } else if ((c1 & 0xF800) != 0xD800) { enc = String.fromCharCode( (c1 >> 12) | 224, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 ); } else { // surrogate pairs if ((c1 & 0xFC00) != 0xD800) { throw new RangeError('Unmatched trail surrogate at ' + n); } var c2 = string.charCodeAt(++n); if ((c2 & 0xFC00) != 0xDC00) { throw new RangeError('Unmatched lead surrogate at ' + (n - 1)); } c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000; enc = String.fromCharCode( (c1 >> 18) | 240, ((c1 >> 12) & 63) | 128, ((c1 >> 6) & 63) | 128, (c1 & 63) | 128 ); } if (enc !== null) { if (end > start) { utftext += string.slice(start, end); } utftext += enc; start = end = n + 1; } } if (end > start) { utftext += string.slice(start, stringl); } return utftext; } function md5(str) { var str = str.toLowerCase(); var xl; var rotateLeft = function(lValue, iShiftBits) { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); }; var addUnsigned = function(lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8); } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8); } } else { return (lResult ^ lX8 ^ lY8); } }; var _F = function(x, y, z) { return (x & y) | ((~x) & z); }; var _G = function(x, y, z) { return (x & z) | (y & (~z)); }; var _H = function(x, y, z) { return (x ^ y ^ z); }; var _I = function(x, y, z) { return (y ^ (x | (~z))); }; var _FF = function(a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _GG = function(a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _HH = function(a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var _II = function(a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b); }; var convertToWordArray = function(str) { var lWordCount; var lMessageLength = str.length; var lNumberOfWords_temp1 = lMessageLength + 8; var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; var lWordArray = new Array(lNumberOfWords - 1); var lBytePosition = 0; var lByteCount = 0; while (lByteCount < lMessageLength) { lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount) << lBytePosition)); lByteCount++; } lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); lWordArray[lNumberOfWords - 2] = lMessageLength << 3; lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; return lWordArray; }; var wordToHex = function(lValue) { var wordToHexValue = '', wordToHexValue_temp = '', lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) { lByte = (lValue >>> (lCount * 8)) & 255; wordToHexValue_temp = '0' + lByte.toString(16); wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2); } return wordToHexValue; }; var x = [], k, AA, BB, CC, DD, a, b, c, d, S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9, S23 = 14, S24 = 20, S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21; str = utf8_encode(str); x = convertToWordArray(str); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; xl = x.length; for (k = 0; k < xl; k += 16) { AA = a; BB = b; CC = c; DD = d; a = _FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); d = _FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); c = _FF(c, d, a, b, x[k + 2], S13, 0x242070DB); b = _FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); a = _FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); d = _FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); c = _FF(c, d, a, b, x[k + 6], S13, 0xA8304613); b = _FF(b, c, d, a, x[k + 7], S14, 0xFD469501); a = _FF(a, b, c, d, x[k + 8], S11, 0x698098D8); d = _FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); c = _FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); b = _FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); a = _FF(a, b, c, d, x[k + 12], S11, 0x6B901122); d = _FF(d, a, b, c, x[k + 13], S12, 0xFD987193); c = _FF(c, d, a, b, x[k + 14], S13, 0xA679438E); b = _FF(b, c, d, a, x[k + 15], S14, 0x49B40821); a = _GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); d = _GG(d, a, b, c, x[k + 6], S22, 0xC040B340); c = _GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); b = _GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); a = _GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); d = _GG(d, a, b, c, x[k + 10], S22, 0x2441453); c = _GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); b = _GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); a = _GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); d = _GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); c = _GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); b = _GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); a = _GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); d = _GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); c = _GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); b = _GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); a = _HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); d = _HH(d, a, b, c, x[k + 8], S32, 0x8771F681); c = _HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); b = _HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); a = _HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); d = _HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); c = _HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); b = _HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); a = _HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); d = _HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); c = _HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); b = _HH(b, c, d, a, x[k + 6], S34, 0x4881D05); a = _HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); d = _HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); c = _HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); b = _HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); a = _II(a, b, c, d, x[k + 0], S41, 0xF4292244); d = _II(d, a, b, c, x[k + 7], S42, 0x432AFF97); c = _II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); b = _II(b, c, d, a, x[k + 5], S44, 0xFC93A039); a = _II(a, b, c, d, x[k + 12], S41, 0x655B59C3); d = _II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); c = _II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); b = _II(b, c, d, a, x[k + 1], S44, 0x85845DD1); a = _II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); d = _II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); c = _II(c, d, a, b, x[k + 6], S43, 0xA3014314); b = _II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); a = _II(a, b, c, d, x[k + 4], S41, 0xF7537E82); d = _II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); c = _II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); b = _II(b, c, d, a, x[k + 9], S44, 0xEB86D391); a = addUnsigned(a, AA); b = addUnsigned(b, BB); c = addUnsigned(c, CC); d = addUnsigned(d, DD); } var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); return temp.toLowerCase(); }
プライバシー
ユーザのプライバシー保護は、Criteoが掲げる最優先事項の1つです。Criteoは、将来にわたっていかなる個人情報も保持することはありません。顧客のプライバシー保護の観点から、Criteoはサーバーで暗号化された顧客のEメールアドレスのみを保持しています。この暗号化は元に戻せないプロセスが採用され、匿名性が常に確保されます。
Criteoは個人の識別が可能ないかなる情報(PII)も直接収集または処理することはありません。クロスデバイスパラメータでユーザの適合を行う際には「匿名」の情報を使用します。
Criteoでは最大限のセキュリティを確保するために、ユーザのEメールアドレスの暗号化はSHA-256ハッシュを使用して行っています。SHA-256でEメールをハッシュ化することにより、唯一の永続的な識別子が生成され、さまざまなデバイスやクライアントのWebサイト(上記参照)のユーザを識別できるようになると同時に、これらがお客様の顧客個人の特定に使用されることは一切ありません。Criteoはいかなる場合も、ハッシュ化されていないEメールアドレスを保持することはありません。
また、Criteoはプライバシーポリシーとオプトアウトソリューションの提供を通じて、ユーザに向けた完全な透明性を確保しています。さらにCriteoは、パートナーに対してもパートナー側のプライバシーポリシーを通じて、Criteoのサービスや方法論に対する透明性を確保するよう求めています。つまり、ユーザはすべての段階/状況においてCriteoのサービスに関する情報にアクセスでき、いつでもサービスのオプトアウトを行うことができます。