ウェブサイトを運営している国によっては、訪問者に関するデータを収集する前に同意を管理する必要がある場合があります。詳細については ドキュメント を参照してください。
クロスデバイス履歴調整
Kameleoon のクロスデバイス履歴調整機能は、異なるデバイスをまたいでユーザーの履歴とアクションをマージします。ユーザーが異なるデバイスで複数回ウェブサイトを訪問した場合、Kameleoon は彼らをリピーター訪問者として識別し、訪問回数を正確に報告します。この機能は、通常は顧客ログインによってユーザーを識別できる限り、簡単に有効化できます。
クロスデバイス履歴調整を使用することで、3つの重要な利点が得られます:
- すべてのデバイスでの訪問とアクションを考慮した一貫したターゲティングシステム。
- 訪問者が使用しているデバイスに関係なく、特定のA/B実験で同じバリエーションを見られるようにします。
- ユニーク訪問者を正しくカウントする正確で精密なレポートシステム。
この機能について詳しくは、この ドキュメント を参照してください。
ITP 管理
ウェブサイトのトラフィックの大部分がモバイルデバイスからのものである場合は、Safari の Intelligent Tracking Prevention (ITP) に関する問題を防ぐために Cookie 同期方法を実装してください。ITP 管理の技術的な詳細については、ドキュメント を参照してください。
Safari での ITP 問題を回避するために、フロントエンドとバックエンドの間で visitorCode 識別子(kameleoonVisitorCode Cookie 経由)を同期するためのいくつかのオプションが利用可能です。これらのオプションには以下が含まれます:
- フロントウェブサーバーまたは Content Delivery Network (CDN) の設定を変更して、kameleoonVisitorCode Cookie を生成・追加する。Kameleoon は Akamai 用の手順を提供できます。
- バックエンドサーバー(Java、NodeJS、または他の言語)に特定のコードスニペットを実装する。
Nginx コードスニペット
Nginx との統合には、以下のコードスニペットを使用してください:
server {
listen 80;
server_name MY_DOMAIN;
set $visitorCode "";
if ($http_cookie ~* "kameleoonVisitorCode=([^;]+)") {
set $visitorCode $1;
}
if ($visitorCode = "") {
set_by_lua_block $visitorCode '{
local alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
local code = ""
for i = 1, 16 do
local randomNumber = math.random(1, #alphabet)
code = code .. alphabet:sub(randomNumber, randomNumber)
end
return code
}';
}
location / {
add_header Set-Cookie "kameleoonVisitorCode=$visitorCode; Expires=$expires; Path=/; Domain=MY_DOMAIN;";
return 204;
}
}
バックエンドコードスニペット
バックエンドコードスニペットのいずれかを、メインのトップレベルドメインに属する単一の URL または各ページにホストできます。単一のエンドポイントを選択した場合、Kameleoon は指定されたエンドポイントにセッションごとに1回呼び出しを行い、サーバーが kameleoonVisitorCode Cookie を設定するようにします。この呼び出しは非同期で、ページの読み込みが完了した後に発生します。このオプションを有効にするには、Customer Success Manager にお問い合わせください。Kameleoon には選択した URL が必要です。
作成する同期エンドポイントはデータを返す必要はありません。204 No Content レスポンスコードで十分です。このエンドポイントはサーバー側 Cookie を設定するためだけに使用され、以下のコードを使って定義した同期 URL に送信される GET リクエストを受け付ける必要があります:const e = new XMLHttpRequest;
e.open("GET", Kameleoon.Internals.configuration.synchronizationEndpointURL + "?visitorCode=" + this.visitorCode, !0);
各ページにバックエンドコードスニペットを埋め込む場合、追加のアクションは不要です。サーバーへの通常のページリクエストが行われたときに、Cookie が自動的に作成されます。
自動生成に依存する代わりに、データベースからの一意の識別子など、独自の visitor code を提供できます。実験のために正確なデータを保証するには、提供する visitorCode が訪問者ごとに一意であることを確認してください。
Kameleoon の Web 実験と Feature 実験の両方を サーバーサイド SDK のいずれかで使用している場合は、getVisitorCode() メソッドを直接使用できます。このヘルパーメソッドは、現在の訪問者の Kameleoon visitor code を自動的に取得し、バックエンドで Cookie を作成します。
javax.servlet.http.HttpServletRequest request; // Provide a reference to the HttpServletRequest
javax.servlet.http.HttpServletResponse response; // Provide a reference to the HttpServletResponse
String topLevelDomain = "MY_DOMAIN";// Here you must provide your own base domain, eg mydomain.com
String visitorCode = null; // Here you can provide your own identifier if needed, else it will be generated randomly
String cookiesHeader = request.getHeader("Cookie");
if (cookiesHeader != null) {
String[] cookies = cookiesHeader.split(";");
for (String cookieNameAndValue : cookies) {
String[] cookieNameAndValuePair = cookieNameAndValue.split("=");
if (cookieNameAndValuePair[0].trim().equals("kameleoonVisitorCode")) {
visitorCode = cookieNameAndValuePair[1];
}
}
}
if (visitorCode == null) {
final String alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
final int alphabetLength = alphabet.length();
final int visitorCodeLength = 16;
final StringBuilder visitorCodeBuilder = new StringBuilder(visitorCodeLength);
for (int i = 0; i < visitorCodeLength; ++i) {
visitorCodeBuilder.append(
alphabet.charAt(java.util.concurrent.ThreadLocalRandom.current().nextInt(alphabetLength))
);
}
visitorCode = visitorCodeBuilder.toString();
}
javax.servlet.http.Cookie cookie = new Cookie("kameleoonVisitorCode", visitorCode);
cookie.setMaxAge(32_832_000);
cookie.setHttpOnly(false); // The cookie must be accessible from the front-end since it stores the visitorCode, which Kameleoon uses to bucket users into experiments and track their activity.
cookie.setPath("/");
cookie.setDomain(topLevelDomain);
response.addCookie(cookie);
NodeJS
let topLevelDomain = "MY_DOMAIN";// Here you must provide your own base domain, eg mydomain.com
let visitorCode = null; // Here you can provide your own identifier if needed, else it will be generated randomly
request.headers && request.headers.cookie.split(';').forEach(function (cookie) {
let cookieNameAndValuePair = cookie.match(/(.*?)=(.*)$/);
if (cookieNameAndValuePair[1].trim() == "kameleoonVisitorCode") {
visitorCode = cookieNameAndValuePair[2].trim();
}
});
if (!visitorCode) {
let alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
let alphabetLength = alphabet.length;
visitorCode = "";
for (let i = 0; i < 16; ++i) {
let randomNumber = Math.floor(Math.random() * alphabetLength);
visitorCode += alphabet[randomNumber];
}
}
let expires = new Date(new Date().getTime() + 32832000000);
response.writeHead(200, {
'Set-Cookie': [`kameleoonVisitorCode=${visitorCode}; expires=${expires}; path=/; domain=${topLevelDomain};`]
});
<?php
$topLevelDomain = "MY_DOMAIN";// Here you must provide your own base domain, eg mydomain.com
$visitorCode = NULL; // Here you can provide your own identifier if needed, else it will be generated randomly
if (isset($_COOKIE["kameleoonVisitorCode"])) {
$visitorCode = $_COOKIE["kameleoonVisitorCode"];
}
if (is_null($visitorCode)) {
$alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
$alphabetLength = strlen($alphabet);
$visitorCode = "";
for ($i = 0; $i < 16; $i++) {
$randomNumber = floor((mt_rand() / mt_getrandmax()) * $alphabetLength);
$visitorCode .= substr($alphabet, $randomNumber, 1);
}
}
setcookie("kameleoonVisitorCode", $visitorCode, time() + 32832000, "/", $topLevelDomain);
?>
このコードをコピー&ペーストし、MY_DOMAIN をベースのトップレベルドメイン(例: mydomain.com)に置き換えてください。
System.Security.Cryptography.RandomNumberGenerator rng; // A concurrent RNG for generating unique visitor codes
Microsoft.AspNetCore.Http.HttpRequest request; // Provide a reference to the HttpRequest
Microsoft.AspNetCore.Http.HttpResponse response; // Provide a reference to the HttpResponse
string topLevelDomain = "MY_DOMAIN";// Here you must provide your own base domain, eg mydomain.com
string visitorCode = null; // Here you can provide your own identifier if needed, else it will be generated randomly
if (request.Cookies.ContainsKey("kameleoonVisitorCode"))
visitorCode = request.Cookies["kameleoonVisitorCode"];
if (visitorCode == null)
{
const string alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
const int visitorCodeLength = 16;
char[] visitorCodeBuffer = new char[visitorCodeLength];
byte[] randBuffer = new byte[visitorCodeLength];
rng.GetBytes(randBuffer);
for (int i = 0; i < visitorCodeLength; i++)
visitorCodeBuffer[i] = alphabet[randBuffer[i] % alphabet.Length];
visitorCode = new string(visitorCodeBuffer);
}
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions.CookieOptions();
cookieOptions.Expires = DateTime.Now.AddSeconds(32_832_000);
cookieOptions.HttpOnly = false; // The cookie must be accessible from the front-end since it stores the visitorCode, which Kameleoon uses to bucket users into experiments and track their activity.
cookieOptions.Path = "/";
cookieOptions.Domain = topLevelDomain;
response.Cookies.Append("kameleoonVisitorCode", visitorCode, cookieOptions);
System.Security.Cryptography.RandomNumberGenerator rng; // A concurrent RNG for generating unique visitor codes
System.Web.HttpRequest request; // Provide a reference to the HttpRequest
System.Web.HttpResponse response; // Provide a reference to the HttpResponse
string topLevelDomain = "MY_DOMAIN";// Here you must provide your own base domain, eg mydomain.com
string visitorCode = null; // Here you can provide your own identifier if needed, else it will be generated randomly
if (request.Cookies.Get("kameleoonVisitorCode") != null)
visitorCode = request.Cookies.Get("kameleoonVisitorCode").Value;
if (visitorCode == null)
{
const string alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
const int visitorCodeLength = 16;
char[] visitorCodeBuffer = new char[visitorCodeLength];
byte[] randBuffer = new byte[visitorCodeLength];
rng.GetBytes(randBuffer);
for (int i = 0; i < visitorCodeLength; i++)
visitorCodeBuffer[i] = alphabet[randBuffer[i] % alphabet.Length];
visitorCode = new string(visitorCodeBuffer);
}
var cookie = new System.Web.HttpCookie("kameleoonVisitorCode", visitorCode);
cookie.Expires = DateTime.Now.AddDays(380);
cookie.HttpOnly = false; // The cookie must be accessible from the front-end since it stores the visitorCode, which Kameleoon uses to bucket users into experiments and track their activity.
cookie.Path = "/";
cookie.Domain = topLevelDomain;
response.Cookies.Add(cookie);
var request *fasthttp.Request // Provide a reference to the Request
var response *fasthttp.Response // Provide a reference to the Response
const topLevelDomain = "MY_DOMAIN" // Here you must provide your own base domain, eg mydomain.com
var visitorCode string // Here you can provide your own identifier if needed, else it will be generated randomly
if binaryVisitorCode := request.Header.Cookie("kameleoonVisitorCode"); binaryVisitorCode != nil {
visitorCode = string(binaryVisitorCode)
}
if visitorCode == "" {
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
const visitorCodeLength = 16
visitorCodeBuilder := strings.Builder{}
visitorCodeBuilder.Grow(visitorCodeLength)
randomBuffer := make([]byte, visitorCodeLength)
if _, err := rand.Read.Read(randomBuffer); err != nil { // crypto/rand
// handle error
}
for i := 0; i < visitorCodeLength; i++ {
visitorCodeBuilder.WriteByte(alphabet[randomBuffer[i] % len(alphabet)])
}
visitorCode = visitorCodeBuilder.String()
}
ck := fasthttp.AcquireCookie()
ck.SetKey("kameleoonVisitorCode")
ck.SetValue(visitorCode)
ck.SetExpire(time.Now().Add(380 * 24 * time.Hour))
ck.SetHTTPOnly(false) // The cookie must be accessible from the front-end since it stores the visitorCode, which Kameleoon uses to bucket users into experiments and track their activity.
ck.SetPath("/")
ck.SetDomain(topLevelDomain)
response.Header.SetCookie(ck)
fasthttp.ReleaseCookie(ck)
Python
import random
topLevelDomain = "MY_DOMAIN" # Here you must provide your own base domain, eg mydomain.com
# Here you can provide your own identifier via customer_visitor_code if needed, else it will be generated randomly
def fill_visitor_code(request, response, customer_visitor_code):
visitor_code = request.cookies.get("kameleoonVisitorCode")
if "kameleoonVisitorCode" in request.cookies:
visitor_code = request.cookies.get("kameleoonVisitorCode")
else:
visitor_code = customer_visitor_code if customer_visitor_code is not None else "".join(
random.choice(string.ascii_lowercase + string.digits) for _ in range(16)
)
response.set_cookie("kameleoonVisitorCode", visitor_code, max_age=32832000, domain=topLevelDomain)
fill_visitor_code(request, response) # The method must be called with correct arguments (depending on your Python web framework)
# Define constants
KAMELEOON_COOKIE_VALUE_LENGTH = 16
KAMELEOON_COOKIE_NAME = 'kameleoonVisitorCode'.freeze
EXPIRE_DAYS = 365
# Method to generate a random visitor code
def generate_visitor_code(length)
alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'
alphabet_length = alphabet.length
visitor_code = ''
length.times do
random_number = rand(alphabet_length)
visitor_code.concat(alphabet[random_number])
end
visitor_code
end
# Main code
top_level_domain = 'MY_DOMAIN' # Replace with your actual domain
visitor_code = cookies[KAMELEOON_COOKIE_NAME]
visitor_code = generate_visitor_code(KAMELEOON_COOKIE_VALUE_LENGTH) if visitor_code.nil? || visitor_code.empty?
kameleoon_cookie = {
value: visitor_code,
expires: Time.now + 60 * 60 * 24 * EXPIRE_DAYS,
path: '/',
domain: top_level_domain
}
cookies[KAMELEOON_COOKIE_NAME] = kameleoon_cookie
カスタムドメインの使用
Kameleoon のデフォルトドメインの代わりに独自のドメインを使用したい場合、または広告ブロッカーによって一部のユーザーが実験に含まれないようにする必要がある場合、Kameleoon はカスタムドメインをセットアップして検出を回避するためのプレミアムオプションを提供しています。
カスタムドメインを有効にする方法について詳しく学ぶ。
独自の CDN またはホスティングサーバーを使用する(セルフホスティング)
Kameleoon アプリケーションファイル engine.js(旧名: kameleoon.js)は、Kameleoon CDN または独自の CDN/サーバー上でホストできます。独自のサーバーでホストすると、Kameleoon CDN が必要とする追加の DNS クエリと SSL ハンドシェイクを回避することで、わずかなパフォーマンスの向上が得られる場合があります。さらに、セルフホスティングはセキュリティ上の理由で好まれることがあります。社内のセキュリティポリシーへの準拠を保証し、ホスティングサーバーのセキュリティに責任を持つことができるためです。
Kameleoon アプリケーションファイルをセルフホストしたい場合は、セルフホスティング のドキュメントを参照してください。