> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kameleoon.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 高度なオプション

> このガイドでは、Kameleoonが提供する追加の高度な実装オプションについて説明します。

## 同意管理

ウェブサイトを運営している国によっては、訪問者に関するデータを収集する前に同意を管理する必要がある場合があります。詳細については [ドキュメント](../../privacy-and-compliance/consent-management) を参照してください。

## クロスデバイス履歴調整

Kameleoon のクロスデバイス履歴調整機能は、異なるデバイスをまたいでユーザーの履歴とアクションをマージします。ユーザーが異なるデバイスで複数回ウェブサイトを訪問した場合、Kameleoon は彼らをリピーター訪問者として識別し、訪問回数を正確に報告します。この機能は、通常は顧客ログインによってユーザーを識別できる限り、簡単に有効化できます。

クロスデバイス履歴調整を使用することで、3つの重要な利点が得られます:

* すべてのデバイスでの訪問とアクションを考慮した一貫したターゲティングシステム。
* 訪問者が使用しているデバイスに関係なく、特定のA/B実験で同じバリエーションを見られるようにします。
* ユニーク訪問者を正しくカウントする正確で精密なレポートシステム。

この機能について詳しくは、この [ドキュメント](../../cross-device-experimentation) を参照してください。

## ITP 管理

ウェブサイトのトラフィックの大部分がモバイルデバイスからのものである場合は、Safari の Intelligent Tracking Prevention (ITP) に関する問題を防ぐために Cookie 同期方法を実装してください。ITP 管理の技術的な詳細については、[ドキュメント](../technical-concepts/itp-management) を参照してください。

Safari での ITP 問題を回避するために、フロントエンドとバックエンドの間で **visitorCode** 識別子(**kameleoonVisitorCode** Cookie 経由)を同期するためのいくつかのオプションが利用可能です。これらのオプションには以下が含まれます:

* フロントウェブサーバーまたは Content Delivery Network (CDN) の設定を変更して、**kameleoonVisitorCode** Cookie を生成・追加する。Kameleoon は Akamai 用の手順を提供できます。
* [バックエンドサーバー](#java)(Java、NodeJS、または他の言語)に特定のコードスニペットを実装する。

### Nginx コードスニペット

Nginx との統合には、以下のコードスニペットを使用してください:

```text theme={null}
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 が必要です。

<Note>
  作成する同期エンドポイントはデータを返す必要はありません。`204 No Content` レスポンスコードで十分です。このエンドポイントはサーバー側 Cookie を設定するためだけに使用され、以下のコードを使って定義した同期 URL に送信される `GET` リクエストを受け付ける必要があります:

  ```text theme={null}
  const e = new XMLHttpRequest;
  e.open("GET", Kameleoon.Internals.configuration.synchronizationEndpointURL + "?visitorCode=" + this.visitorCode, !0);
  ```
</Note>

各ページにバックエンドコードスニペットを埋め込む場合、追加のアクションは不要です。サーバーへの通常のページリクエストが行われたときに、Cookie が自動的に作成されます。

<Check>
  自動生成に依存する代わりに、データベースからの一意の識別子など、独自の **visitor code** を提供できます。実験のために正確なデータを保証するには、提供する visitorCode が訪問者ごとに一意であることを確認してください。
</Check>

Kameleoon の Web 実験と Feature 実験の両方を [サーバーサイド SDK](../../feature-experimentation/get-started/overview#サーバーサイド-sdk) のいずれかで使用している場合は、`getVisitorCode()` メソッドを直接使用できます。このヘルパーメソッドは、現在の訪問者の Kameleoon **visitor code** を自動的に取得し、バックエンドで Cookie を作成します。

#### Java

```java theme={null}
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

```js theme={null}
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

```php theme={null}
<?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)に置き換えてください。

#### C\#

<Tabs>
  <Tab title=".NET Core">
    ```csharp theme={null}
    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);
    ```
  </Tab>

  <Tab title=".NET Framework">
    ```csharp theme={null}
    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);
    ```
  </Tab>
</Tabs>

#### Go

```go theme={null}
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

```python theme={null}
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)
```

#### Ruby

```ruby theme={null}
# 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 はカスタムドメインをセットアップして検出を回避するためのプレミアムオプションを提供しています。

[カスタムドメインを有効にする方法について詳しく学ぶ。](../../feature-experimentation/technical-reference/faq-global#how-do-ad-blockers-affect-kameleoon)

## 独自の CDN またはホスティングサーバーを使用する(セルフホスティング)

Kameleoon アプリケーションファイル `engine.js`(旧名: `kameleoon.js`)は、Kameleoon CDN または独自の CDN/サーバー上でホストできます。独自のサーバーでホストすると、Kameleoon CDN が必要とする追加の DNS クエリと SSL ハンドシェイクを回避することで、わずかなパフォーマンスの向上が得られる場合があります。さらに、セルフホスティングはセキュリティ上の理由で好まれることがあります。社内のセキュリティポリシーへの準拠を保証し、ホスティングサーバーのセキュリティに責任を持つことができるためです。

Kameleoon アプリケーションファイルをセルフホストしたい場合は、[セルフホスティング](../self-hosting/simple-self-hosting-and-on-premises-options#アプリケーションファイルのセルフホスティング) のドキュメントを参照してください。
