どのようにお手伝いできますか?

[Beta機能]AppsFlyer Web SDK の実装

  • 更新

概要:AppsFlyer Web SDK(ピクセルとも呼ばれます)をWebサイトに実装することで、ユーザーの訪問やイベントをAppsFlyerへ送信できるようになります。

概要

Web SDK を使用すると、訪問者がWebサイト上でどのように行動したかを記録し、その情報をAppsFlyerへ送信できます。これは40〜60KBのプラグインモジュールで、Webサイト上でのユーザー訪問やアクションをAppsFlyerプラットフォームへレポートします。

Integrate the SDK manually

 以下の手順に従って、インストールから検証、プライバシー制御まで、Web SDK の実装を完了してください。

  1. キーの取得:Web SDK ID(Web Dev Keyとも呼ばれます)を取得します。 Obtain the Web SDK ID (also known as Web Dev Key).
  2. コードスニペットの選択:連携タイプとセキュリティ要件に合ったスニペットを選択します。 Choose the snippet that matches your integration type and security requirements.
  3. Web SDKのデプロイ:ネイティブスニペット、Google Tag Manager、またはAdobe Launch Tag Managerを使用してSDKをデプロイします。 Deploy the SDK using a native snippet, Google Tag Manager, or Adobe Launch Tag Manager.
  4. SDKが機能していることを確認:ブラウザのデベロッパーツールでネットワークコールを確認し、SDKがリクエストを送信していることを検証します。 Validate that the SDK sends requests by checking network calls in the browser developer tools.
  5. Set and record events. イベントの設定・記録:ネイティブJavaScriptまたはGoogle Tag Managerを使用して、ページ読み込み時またはユーザー操作時にカスタムイベントを定義し、送信します。
  6. カスタマーユーザーIDの設定:永続的なCUIDを設定し、Web上のアクティビティを他のプラットフォームと統合します。 Set a persistent CUID to unify web activity with other platforms.
  7. Manage privacy. プライバシー設定の管理:計測のオプトインまたはオプトアウトを管理し、セキュリティとデータフィルタリング(Content Security Policyおよびクエリパラメータの破棄)を設定します。
  8. Web SDK Cookieのリファレンス:Web SDKが設定または使用するCookieについて、目的、有効期間、スコープを確認します。 Review the cookies the Web SDK sets or uses, including purpose, lifespan, and scope.

Integrate the SDK with an AI coding agent

Instead of manually integrating the Web SDK (see steps below), use an AI coding tool (Cursor, Claude Code, Codex, Copilot) to implement the entire integration for you. Copy the prompt, replace the two placeholders, and paste it into your AI coding tool.

This approach streamlines and covers all the steps below, but you still need to make sure the SDK works correctly and review your privacy configuration afterward.

Before copying the prompt, replace:

  • <WEB_SDK_ID>: In AppsFlyer, go to App Settings, select your web app (your website domain with the "website-" prefix), and copy the Web SDK ID from SDK authentication.
  • <PRODUCTION_URL>: Your live site URL, used for post-deploy verification.

The AI tool builds an event plan from your codebase and waits for your approval before implementing it. Review the plan, confirm that revenue and currency values appear only on realized-revenue events, and verify the results using the post-deploy verification steps in the prompt.

AI implementation prompt
# **AppsFlyer Web SDK - AI implementation prompt**

Copy the prompt below into an AI coding tool that can edit your project (Cursor, Claude Code, Codex, Copilot). Before copying, replace two placeholders:

  - <WEB_SDK_ID> - in AppsFlyer, go to My Apps, select your web app (your domain with the website- prefix), and copy the Web SDK ID (also called Web Dev Key) from SDK authentication.
  - <PRODUCTION_URL> - your live site URL, used for post-deploy verification.

Implement the AppsFlyer Web SDK (web attribution pixel) on this website, including the events that matter for my marketing measurement.

My Web SDK ID: <WEB_SDK_ID>

My production URL: <PRODUCTION_URL>

## Step 0 - Config gate

If the Web SDK ID above is missing or still a placeholder, reply ONLY with a short request for it (in AppsFlyer: My Apps > the "website-" prefixed app > SDK authentication > Web SDK ID) and stop. Do not write any code until it is provided. If the production URL is missing, request it in the same reply - it is required for post-deploy verification.

Work with minimal diffs: infer file paths from the repo, change only what this integration requires, and preserve the project's existing patterns.

## Step 1 - Analyze the site first

Before writing any code, review the codebase and build the event plan yourself - do not ask me to list the events:

1. Identify the framework (plain HTML, React, Next.js, Vue, etc.) and where the document <head> is controlled.

2. Discover the conversion actions from the code. Look in, in order of reliability:

   - Existing analytics calls: gtag()/GA4 events, Segment analytics.track(), fbq('track'), dataLayer.push (including ecommerce objects) - these tell you both the actions and where the values (amount, currency, order ID) already live.

   - Commerce logic: checkout/cart modules, order-confirmation and thank-you pages/routes, payment-success callbacks.

   - Auth logic: signup and login flows, and where the internal user ID becomes available in client code.

   - Forms and CTAs: lead forms, subscription/trial starts, downloads.

   - Non-commerce / tool products: if the site has no purchase, cart, checkout, signup, or login flows, do not invent commerce or auth events. Identify the real product actions (e.g. generate, copy, export, download, share, template select, parameter edit) and map those to custom descriptive event names instead.

3. Map each discovered action to the AppsFlyer standard name:

   - completed order / "Order Completed" / purchase_success -> af_purchase (with eventRevenue)

   - signup / register / account created -> af_complete_registration

   - login / signin -> af_login

   - add to cart / "Product Added" -> af_add_to_cart (af_price, no eventRevenue)

   - begin checkout / "Checkout Started" -> af_initiated_checkout (af_price, no eventRevenue)

   - product or content view -> af_content_view

   - subscription started -> af_subscribe; free trial started -> af_start_trial

   - search -> af_search

   Anything with no standard equivalent keeps a descriptive custom name.

4. For each event, identify in the code the exact source of: the amount actually charged (for af_purchase), currency, order/transaction ID, and the user ID. Reuse the same data sources the existing analytics reads from.

5. Check for an existing consent management platform (CMP) such as OneTrust or Didomi. Also flag any homegrown consent toggle or privacy preference stored by the site, and ask me how it should gate measurement rather than deciding for me.

Note: existing analytics are discovery input only - implement AppsFlyer events as direct AF() calls, not relayed through Segment/GA4 with their names.

Then show me the proposed event plan as a table (AppsFlyer event name, trigger + file, revenue/af_price source, dedup ID source) and wait for my approval before implementing. Flag any event where you could not locate the value source instead of guessing.

## Step 2 - Install the SDK snippet

Add this snippet near the top of the <head> on every page, with my Web SDK ID:

<script>

!function(t,e,n,s,a,c,i,o,p){t.AppsFlyerSdkObject=a,t.AF=t.AF||function(){

(t.AF.q=t.AF.q||[]).push([Date.now()].concat(Array.prototype.slice.call(arguments)))},

t.AF.id=t.AF.id||i,t.AF.plugins={},o=e.createElement(n),p=e.getElementsByTagName(n)[0],o.async=1,

o.src="https://websdk.appsflyer.com?"+(c.length>0?"st="+c.split(",").sort().join(",")+"&":"")+(i.length>0?"af_id="+i:""),

p.parentNode.insertBefore(o,p)}(window,document,"script",0,"AF","pba",{pba: {webAppId: "<WEB_SDK_ID>"}})

</script>

Hard rules:

- Use the snippet verbatim. Do NOT rewrite it as a custom component or wrapper module. Wrapped SDKs can send custom events while the automatic visit (the SDK's LOAD event) never fires - the site then shows zero visits and nothing can be attributed.

- The SDK must load exactly ONCE per page load. In React/Next.js, guard against re-renders and double-mounting (e.g. load it in the root HTML/document template, not inside a component that re-mounts). Multiple loads can stop the SDK from working.

- If the site already loads the AppsFlyer SDK via a tag manager (GTM), do NOT add it in code as well - one loader, not two. Tell me if you find an existing AppsFlyer tag.

- Do NOT implement a page-view or visit event manually. The SDK records visits automatically on load; a hand-rolled "page_view" event will never count as a visit.

- The config key is webAppId (not appId).

- If the site enforces a strict Content Security Policy with nonces, add the nonce to the inline snippet tag AND make sure the policy includes 'strict-dynamic' - the snippet injects the SDK script dynamically, and without 'strict-dynamic' a nonce-only policy blocks it.

## Step 3 - Implement events

Event call format:

AF('pba', 'event', {

  eventType: 'EVENT',            // always the literal string 'EVENT'

  eventName: 'af_purchase',

  eventRevenue: 49.99,           // top level - only on realized revenue

  eventRevenueCurrency: 'USD',   // top level - 3-letter ISO code, defaults to USD if omitted

  eventValue: {                  // JSON metadata, max 1000 characters

    "af_order_id": "TXN-12345",

    "af_customer_event_id": "evt-abc-001"

  }

});

Event rules - follow these exactly:

1. Use AppsFlyer standard event names so cross-platform reporting and funnels align: af_purchase, af_complete_registration, af_login, af_add_to_cart, af_initiated_checkout, af_content_view, af_subscribe. If a mobile app exists, use the SAME event names as the mobile SDK. Never add platform suffixes like "_web".

   Exception - distinct purchase lines: if the site clearly sells distinct product tiers or categories that need separate dashboard breakdowns (e.g. two subscription products), propose split names in the event plan (af_purchase_<tier>) instead of one generic event, and note why. Segmentation via eventValue alone does not show in standard dashboard views. Never send BOTH a tier-level and a generic event for the same purchase - that duplicates data.

2. Revenue goes ONLY in the top-level eventRevenue field, and ONLY on events where money actually moved (completed purchase, completed subscription, confirmed booking). Values inside eventValue (af_revenue, revenue, price, amount, total) are NEVER counted as revenue - putting revenue there is the #1 implementation mistake and results in $0 revenue on every purchase.

3. Always send eventRevenueCurrency with eventRevenue when the currency is not USD - otherwise every amount is recorded as USD.

4. Send the actual single-transaction amount as a plain number: no currency symbols, no cents-as-units, no cart-total-plus-item duplication, no lifetime value.

5. For monetary values that are NOT realized revenue (add-to-cart value, checkout-started value, browsed price): do NOT set eventRevenue. Put the amount in "af_price" and the currency in "af_currency" inside eventValue. Sending eventRevenue on both af_initiated_checkout and af_purchase double-counts revenue.

6. On purchases, include "af_order_id" (the transaction ID) inside eventValue. If the codebase has no real transaction ID at that point, say so in the event plan instead of substituting a placeholder.

7. Include a unique "af_customer_event_id" inside eventValue on every conversion event. The same event name must never fire twice with the same ID - generate it per action and guard against SPA re-renders firing the handler twice. This also deduplicates against any server-side (S2S) stream sending the same conversions.

8. One event per user action. Do not emit two names for the same action, and do not relay the same action through both AppsFlyer and a forwarding layer with different names.

9. For multi-item carts, add an "af_order_info" array inside eventValue - one object per item with keys: sku, revenue (per-unit price), qty, content_name, content_type, content_category, brand. On a purchase, top-level eventRevenue still carries the order total.

10. Events must fire after the SDK snippet has loaded on the page. For conversions that end on a confirmation/thank-you page, fire the event on that page's load; for in-page actions (button clicks in an SPA), fire from the action handler.

11. Sparse payloads - omit irrelevant fields:

    - Do NOT include eventRevenue or eventRevenueCurrency unless money actually moved on that event. Never send eventRevenue: 0 or a default currency "just in case."

    - Do NOT include eventCategory, eventLabel, or any GA/Segment-style fields. They are not part of the AppsFlyer Web SDK event API.

    - Inside eventValue, omit keys whose values are empty string, null, undefined, or false (unless falsehood itself is meaningful for that property).

    - If a parameter is not relevant for a specific event, do not put it in the payload at all. Prefer a minimal object with only the fields that apply.

    - Empty revenue/currency columns in AppsFlyer reports do not mean the client should send zeros or defaults - leave those fields absent.

## Step 4 - Set the Customer User ID (CUID)

Immediately after a user logs in or signs up (and on page loads where the user is already authenticated), call:

AF('pba', 'setCustomerUserId', '<the user's internal ID, as a string>');

Rules:

- Use the SAME identifier the mobile apps pass to setCustomerUserId, if mobile apps exist - this is what stitches one user's journey across web and mobile.

- Use an opaque internal ID. Never an email address, phone number, or other PII.

- Call it as early as possible - events fired before it will not carry the CUID.

- setCustomerUserId by itself does not create a reportable event. Also fire af_complete_registration on signup and af_login on login, after the CUID is set, so those events carry it.

## Step 5 - Consent (only if a CMP exists)

If the site has a consent management platform:

- Initialize the SDK with measurement off: {pba: {webAppId: "<WEB_SDK_ID>", measurementStatus: false}}

- On consent granted: window.AF_SDK.PLUGINS.PBA.enableMeasurement()

- On consent revoked: window.AF_SDK.PLUGINS.PBA.disableMeasurement()

Notes:

- These plugin methods only exist once the SDK script has finished loading, unlike AF(), which is a queueing stub available immediately. Handle that ordering.

- If measurement starts off, no visit is recorded until consent is granted. Call that trade-off out explicitly before implementing it.

If there is no CMP, use the plain snippet (measurement defaults to on).

## Step 6 - Verify

### 6a. Local verification (during implementation)

Run the project, drive a browser (Playwright/Puppeteer, or a browser tool if you have one), and capture BOTH the request payload and the HTTP response status of every call to appsflyer domains. Assert:

- The SDK loader request returns 200 and fires exactly once per page load (navigate between pages and re-render components to prove no double load).

- A request fires on page load with eventType "LOAD" and a populated afWebUserId, and its response is 2xx - this is the visit; without it nothing will attribute.

- Each implemented conversion produces exactly one event request, each returning 2xx, with eventRevenue and eventRevenueCurrency at the top level on purchases, and af_customer_event_id present and unique.

- After a simulated login, subsequent requests carry the customer user ID.

A captured request is NOT proof of success. An event whose response is 4xx was rejected and will never appear in reporting. Report the status code for every event you fire, and never describe an event as verified without one.

If you cannot run a browser, verify statically: the snippet has a single insertion point that cannot mount twice; every event handler fires exactly once per action; revenue and currency are top-level fields; setCustomerUserId is reachable on every authenticated entry path. Say plainly that no response status could be observed.

### 6b. Post-deploy verification on the real domain (mandatory)

Local runs prove the code path, not the production page. Build pipelines and asset processors can strip, defer, or relocate inline scripts, so checking the source file is not enough. After deployment:

- Fetch the production URL and confirm the snippet is present in the SERVED HTML.

- Load the production page in a browser and repeat every assertion from 6a against it.

- Confirm the af_id query parameter on the outgoing requests carries the Web SDK ID exactly - a wrong or truncated ID means events are sent under an ID that does not exist in my account and they will silently go nowhere.

- Use a dedicated QA customer user ID (for example qa_<yyyymmdd>_01) so the run is isolatable in raw data later.

If I have not deployed yet, tell me 6b is still outstanding and give me the exact commands and assertions to run once I do.

### 6c. QA record

Produce a table of the verification run so the rows can be matched in AppsFlyer raw data afterwards, with one line per event: UTC timestamp, event name, CUID, af_order_id, af_customer_event_id, HTTP status. State the UTC start and end time of the whole run, and the UTC time of the deployment if you know it.

## Step 7 - Reading the data back

Include in the report an explicit guide to confirming the events in AppsFlyer, because visits and conversions are different record types and are easy to confuse:

- Visits are recorded automatically and appear in event-level data as SESSION rows with an EMPTY event name and zero revenue - that is the schema, not a fault. First visits and revisits appear in conversion-level data (FIRST_VISIT / REVISIT), not as named events. A sessions-scoped export can never contain in-app events, no matter how correct the implementation is.

- The implemented conversions appear as separate rows with the event name populated (af_purchase, af_login, and so on), with revenue on purchase rows only.

- Any data pulled for a time window BEFORE the deployment cannot contain the new events. Give me the deployment UTC time and tell me to query only after it. Point out that attribution-time fields can be much older than the event time and refer to a prior visit, not to this run.

- State the expected reporting latency, and warn me not to read an empty report inside that window as a failure.

- Tell me the exact filter to use to find the QA run from 6c (time window plus QA CUID), and what a healthy result looks like.

- If events return 2xx but still do not appear after the latency window, say clearly that this is an account-side issue (event not enabled for the web app, reporting scope, or data access) rather than a code defect, and list what I should check in the AppsFlyer UI.

## Output

When done, give me:

- A table of every event implemented: name, trigger location (file), revenue handling, dedup ID.

- Where the snippet was installed and how single-load is guaranteed.

- Where setCustomerUserId is called.

- The QA record table from 6c, and a clear split of what you verified yourself (with response statuses) versus what remains as a manual QA checklist for me (page to open, action to take, request and status to expect).

- The Step 7 guide to reading the data back.

- Anything you could not implement or need from me (e.g. where the user ID lives, which purchase amount field is the final charged total, any value source you refused to guess).

Do not implement anything beyond the AppsFlyer Web SDK integration described here.

1. キーの取得

Web SDK ID(Web Dev Keyとも呼ばれます)を取得します。

  1. AppsFlyer管理画面の左メニューから、アプリ設定を開きます。
  2. ページ上部のアプリ選択メニューから、Webアプリ(「website-」の接頭辞が付いたWebサイトのドメイン)を選択します。
  3. SDK認証のセクションで、Web SDK IDをコピーします。

Smart Bannerのキーを取得します(必要な場合):

  1. AppsFlyer のサイドメニューから、Engage>Web-to-app>Smart Bannersを選択してください。
  2. 必要な Smart Bannerのキーをコピーしてください。

2. コードスニペットの選択

連携タイプとセキュリティ要件に合ったスニペットを選択します。利用できるオプションは2つあります。

  • スタンダードWeb SDK:標準の連携方法です。
  • アドバンスSDK検証:Web SDKにサプライチェーン保護を追加する、強化された連携方法です。 CDNの侵害、DNSハイジャック、中間者攻撃に対するセキュリティをさらに高めるために使用します。

スタンダードWeb SDKからアドバンスSDK検証へ移行する場合は、既存のスニペットを新しいものに置き換えてください。既存のスニペットに新しいスニペットを追加しないでください。

スタンダードWeb SDK

標準のWeb SDK連携を導入する場合は、このスニペットを使用します。 SDKを読み込みたいすべてのページで、タグの上部付近に貼り付けてください。

Smart Bannersを使用しない場合
<script>
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" } };
  window.AF.plugins = {};

  // Inject SDK
  var o = document.createElement("script"),
      p = document.getElementsByTagName("script")[0];
  o.async = 1;
  // Replace WEB_DEV_KEY with your Web SDK ID
  o.src = "https://websdk.appsflyersdk.com?" + "st=pba&af_id=WEB_DEV_KEY";
  p.parentNode.insertBefore(o, p);
</script>
Smart Bannersを使用する場合
<script>
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" }, banners: { key: "YOUR_BANNER_KEY" } };
  window.AF.plugins = {};

  // Inject SDK
  var o = document.createElement("script"),
      p = document.getElementsByTagName("script")[0];
  o.async = 1;
  // Replace WEB_DEV_KEY with your Web SDK ID
  o.src = "https://websdk.appsflyersdk.com?" + "st=pba,banners&af_id=WEB_DEV_KEY";
  p.parentNode.insertBefore(o, p);
  AF('banners', 'showBanner');
</script>

アドバンスSDK検証

アドバンスSDK検証は、Web SDKにサプライチェーン保護を追加する仕組みです。ユーザーのブラウザで実行されるコードが、AppsFlyerによって公開されたコードそのものであることを保証します。 SDKのソースコード自体はスタンダード連携と同一であり、異なるのは配信および検証の仕組みのみです。

アドバンスSDK検証の特徴は以下の通りです:

  • CDN改ざん、DNSハイジャック、中間者攻撃(MITM)に対する追加のセキュリティレイヤーを提供
  • SDKの読み込み時間が約250ms増加

アドバンスSDK検証は任意機能です。スタンダードな連携も引き続き完全にサポートされており、サードパーティ分析ピクセルにおける一般的な実装方式となっています。アドバンスSDK検証はそれに対して更に追加の保護レイヤーを提供します。

Webサイトでnonceを使用したContent Security Policy(CSP)を適用している場合は、「プライバシー管理」セクション内の「Content Security Policy(CSP)」を参照し、このスニペットのnonce対応版を使用してください。

Smart Bannersを使用しない場合
<script>
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" } };
  window.AF.plugins = {};

  // Manifest loader config
  window.AF_LOADER_CONFIG = {
    baseUrl: "https://websdk.appsflyersdk.com",
    plugins: ["pba"]
  };

  // Inject manifest loader
  var loaderScript = document.createElement("script");
  loaderScript.src = "https://websdk.appsflyersdk.com/manifestLoader.v1.js";
  loaderScript.integrity = "sha384-Uncl2YwvjFpFz0PwEfl3bL/0JsOQcDFEpwXHzcN0MBavn9vvFEx5pZxADTq8h+CV";
  loaderScript.crossOrigin = "anonymous";
  loaderScript.async = true;
  document.head.appendChild(loaderScript);
</script>
Smart Bannersを使用する場合
<script>
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" }, banners: { key: "YOUR_BANNER_KEY" } };
  window.AF.plugins = {};

  // Manifest loader config
  window.AF_LOADER_CONFIG = {
    baseUrl: "https://websdk.appsflyersdk.com",
    plugins: ["banners", "pba"]
  };

  // Inject manifest loader
  var loaderScript = document.createElement("script");
  loaderScript.src = "https://websdk.appsflyersdk.com/manifestLoader.v1.js";
  loaderScript.integrity = "sha384-Uncl2YwvjFpFz0PwEfl3bL/0JsOQcDFEpwXHzcN0MBavn9vvFEx5pZxADTq8h+CV";
  loaderScript.crossOrigin = "anonymous";
  loaderScript.async = true;
  document.head.appendChild(loaderScript);
</script>

3. スニペットのデプロイ

手順2で選択したスニペットを、以下いずれかの方法でデプロイします。 SDKがページごとに1回だけ読み込まれるよう設定してください。

選択肢 A:Webサイトに直接追加する

すべてのページで以下を実施します:

  1. 手順2のスニペット内にある WEB_DEV_KEY を、ご利用のWeb SDK IDに置き換えます(必要に応じて YOUR_BANNER_KEY も置き換えます)。
  2. スニペットをWebサイトの タグ上部付近に貼り付けます。
選択肢 B:Google Tag Manager(GTM)経由でデプロイする

SDKがページごとに1回のみ読み込まれるように設定し、GTMの優先度設定を利用して、ページ読み込み直後に実行されるようにしてください。

  1. Google Tag Managerを開きます。
  2. AppsFlyer Web SDK用の新しいタグを作成します。
  3. タグタイプで「Custom HTML」を選択します。
  4. タグ名をわかりやすい名前に設定します。
  5. 「Tag Configuration」に、手順2のスニペットを貼り付けます。
  6. 保存をクリックします。
  7. トリガーを追加する:
    • すべてのページで実行する場合:
      1. [トリガーの追加] をクリックします。
      2. [すべてのページ] を選択してください。
      3. 保存をクリックします。
      4. タグ名を入力し、[保存]をクリックします。
    • 特定ページのみで実行する場合:
      1. [タグを保存] をクリックします。
      2. GTMメイン画面で「トリガー」を選択し、「New(新規作成)」をクリックします。 Click New.
      3. ペンのアイコンをクリックしてください。
      4. トリガータイプとして「ページビュー(Page View)」を選択します。
      5. [Some Page Views](一部ページビュー)を選択します。
      6. 必要に応じてページ条件とトリガー条件を設定します。
      7. 保存をクリックします。
      8. 作成したトリガーをAppsFlyer Web SDKタグに関連付ける
        1. GTMのメイン画面で「Tags」を選択します。
        2. 以前に作成したタグを選択してください。
        3. トリガーパネル内のペンアイコンをクリックします。
        4. 前に作成したページビュートリガーを選択してください。
        5. 保存をクリックします。

GTMのCustom Templatesは、アドバンスSDK検証ではサポートされていません。 これは、Custom Templatesのサンドボックス環境では、検証に必要な integrity 属性を設定できないためです。代わりに、Custom HTMLのタグタイプを使用してください。

選択肢 C:Adobe Launch Tag Manager経由でデプロイする

Adobe Experience Cloudでプロパティを作成する

  1. Adobe Experience Cloud > Launch へ移動してください。
  2. Adobe Experience Cloud Launch の下にある Go to Launch をクリックします 。
  3. [New Property](新しいプロパティ)をクリックします。
  4. プロパティに名前を付けてください。
  5. Platform の下にある、 Web を選択します。
  6. Webサイトのドメインを入力してください。
  7. 保存をクリックします。

Adobe Launchプロパティにスニペットを追加する

  1. My web property ページで、Rulesタブを選択します。
  2. ルールに名前を付けます。推奨名:Load web SDK
  3. If セクションで、Eventsの下にある +Add をクリックしてください。
    • Event Type にある Core - DOM Ready を選択します
    • Keep Changes(変更を保存)をクリックします。
  4. Then セクションで、Actions の下にある +Add をクリックしてください。
    • アクションの種類でカスタムコードを選択します。
    • 「JavaScript」>「エディタを開く」を選択し、手順2のスニペットを貼り付けます(ラッパー行は含めないでください)。
    • [Keep Changes](変更を保存)をクリックして、コードエディターを閉じます。
  5. 保存をクリックします。

Adobe LaunchタグをWebサイトに追加する

  1. [My web property] ページで、[Environments] タブを選択します。
  2. 公開したい環境(developmentまたはproduction)の行を探します。
  3. 「Install」列の該当行にあるボックスアイコンをクリックします。
  4. 「Web Install Instructions」ダイアログで、スクリプトコードスニペットをコピーし、ダイアログを閉じます。
  5. コピーしたコードスニペットをWebサイトの <head> セクションに貼り付けます。

Adobe Launch環境を公開する

  1. [My web property] ページで、[Publishing] タブに移動します。
  2. [Development]セクションの、[Add New Library] をクリックします。
    • ライブラリに名前を付けて、環境を選択します。
    • Resource Changes の下にある Add a Resource をクリックしてください。
    • Rules > Load web SDK > Latest > Select & Create a New Revision をクリックします。
    • 保存をクリックします。
  3. Developmentのセクションで実施する操作:
    • 新しく作成したライブラリ横のアクションメニュー(3点アイコン)をクリックし、「Build for Development」を選択します。
    • 再度アクションメニューをクリックし、「Submit for Approval」を選択します。
  4. Submittedのセクションで実施する操作:
    • アクションメニューをクリックし、「Build for Staging」を選択します。
    • 再度アクションメニューをクリックし、「Approve for Publishing」を選択します。
  5. Approvedのセクションで実施する操作:
    • アクションメニューをクリックし、「Build & Publish to Production」を選択します。

4. SDKが正しく動作していることを確認する

インストール後、ブラウザのデベロッパーツールでネットワークリクエストを確認し、SDKが正常にリクエストを送信していることを検証してください。

DevTools screenshot

SDKが正しく動作していることを確認するには、以下の手順を実施します:

  1. Webサイトを開いてください。
  2. Open the browser developer tools.
  3. (A)「Network」タブを開きます。
  4. ページを再読み込みします。
  5. (B)appsflyer でフィルタリングします。以下2種類のリクエストが表示される場合があります:
    • SDK loader — リクエストURLが https://websdk.appsflyersdk.com で始まります。これは、SDKスクリプトが正しく読み込まれていることを示します。
    • Event data — リクエストURLが https://wa.appsflyer.com/events で始まります。これは、SDKがイベントデータをAppsFlyerへ送信していることを示します。
  6. (C)eventsメッセージ(wa.appsflyer.com のコール)を選択します。
  7. 「Headers」タブで、(D)以下を確認します。
    • Request URLが https://wa.appsflyer.com/events?site-id= で始まっていること
    • site_id クエリパラメータが WEB_SDK_KEY と一致していること
    • ステータスコードが 200 であること
  8. site_id が、AppsFlyer > 上部メニュー > My Apps に表示されている WEB_SDK_KEY と一致していることを確認します。
  9. SDKが1回だけ読み込まれていることを確認してください。 SDKが複数回読み込まれると、正常に動作しなくなる可能性があります。

For a real-time, visual way to confirm your Web SDK installation and validate that your events fire correctly, use the Web SDK Test page.

5. イベントの設定・記録

Web SDKの初期化後は、単なる訪問計測から、特定のユーザーアクションの計測へ移行できます。このセクションでは、購入や会員登録などのカスタムイベントを定義・記録する方法を、ネイティブJavaScriptまたはGoogle Tag Managerを用いて説明します。

イベントを設定する

イベントはWeb計測の基本要素であり、ビジネス上価値のある特定のユーザーアクションを表します。これらのユーザー行動を計測するには、各イベントのロジックとパラメータを定義し、収益情報やカスタムメタデータなどの適切なイベントパラメータをAppsFlyerプラットフォームへ送信する必要があります。

購入イベントと関連収益を含むイベント例

AF('pba', 'event', {eventType: 'EVENT', eventName: 'purchase', eventRevenue: 12, eventValue: {"key1": 123, "key2": "name"}});
Web SDKのイベントパラメータ一覧
パラメーター名 必須 説明
eventType Yes イベントタイプ。 Format: String. 形式:String常に EVENT を設定してください。例: eventType: "EVENT"
eventName Yes イベント名。 Format: String. 形式:String例:Purchase, Subscription
eventRevenue 任意 コンバージョンイベントに紐づく収益。形式:Float
eventRevenueCurrency 不可 収益通貨。 3文字の ISO 4217 通貨コード。 Default: USD. デフォルト:USD形式:String
eventValue 可能 イベント内容を表すイベントパラメータの一覧。 Use this parameter to send rich in-app events like product SKU and line item price. Format: JSON. 形式:JSON例:{"sku": "ABC123", "color": "blue", "unit_price": 3.99, "currency": "USD"} (制限:文字数は1000文字まで。
ページ読み込み時にイベントを記録する

これは、Thank Youページや確認ページなど、リダイレクトで完了するコンバージョンを計測する際の一般的な実装方法です。

このトリガーは、ネイティブJavaScriptでwindowロードメソッドを追加する方法、またはGoogle Tag Managerでページビュートリガーを設定する方法のいずれかで実装できます。

以下のコード例はあくまで参考例です。そのまま使用せず、必ずご利用サイトの構成に合わせて調整してください。

例:AF Web SDKを使用してイベントを記録する

この方法は、ニュースレター登録後のThank Youページなど、リダイレクトを伴うコンバージョン計測に適しています。

ユースケース:ユーザーがニュースレター登録を完了し、確認ページへリダイレクトされ、確認ページが表示されたタイミングでsubscriptionイベントを記録したい場合。 You want to record the subscription event as soon as that page is visible.

ネイティブページロードの例:

window.onload = function(){
  AF('pba', 'event', {eventType: 'EVENT', eventValue: {'category': 'holiday_promotion'}, eventName: 'subscription'});
}

How it works:

  1. ページが必要なコンテンツを読み込みます。
  2. windowが完全に読み込まれると(window.onload)、スクリプトが自動的に AF() メソッドを呼び出します。
  3. subscriptionイベントと関連メタデータ(categoryおよびlabel)が、AppsFlyerへ直接送信されます。
例:GTM経由でイベントを記録する

この方法では、「Thank You」ページが読み込まれたタイミングでタグを発火させることで、ニュースレター登録などの完了済みコンバージョンを記録します。

1. Thank Youページを設定する

以下のHTML構造ではGTMを読み込み、GTM経由でWeb SDKを読み込みます。また、関数やlocalStorageを使って、GTMで利用できるデータを用意する方法も示しています。

<html>
<head>
    <script>
        // Google Tag Manager loads the Web SDK
        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','GTM-XXXX');
    </script>
    <script>
        function getResponseFromServer() {
            return JSON.stringify({ action: 'subscribe', category: 'site actions', label: userEmail })
        }
        localStorage.setItem('data', JSON.stringify({ action: 'subscribe', category: 'site actions', label: 'user@email.com' }));
    </script>
</head>
<body>
    <h1>Thank You for Subscribing to Our Newsletter</h1>
</body>
</html>

2. GTMタグを設定する

  1. GTMメイン画面で「トリガー」を選択し、「New(新規作成)」をクリックします。
  2. その際、わかりやすい名前を付けてください。 (例:「AF Subscription Event」など)
  3. HTMLのテキストエリアに、以下のスクリプトを貼り付けます。

    AF('pba', 'event', {eventType: 'EVENT', eventValue: {'category' : 'holiday_promotion'}, eventName: 'subscription'});
  4. テキストエリア下部の「Advanced Settings」を展開し、続いて「Tag Sequencing」を開きます。タグの実行後にコンバージョンが発火するよう設定されていることを確認してください。
  5. このタグが「Thank You」ページのPage Viewで発火するよう、トリガーを設定してください。
ユーザー操作時にイベントを記録する

ページを再読み込みせずに発生するアクション(ボタンクリック、ダウンロード、カート追加など)を計測する場合に使用します。

通常、このような操作は、ネイティブHTML要素にクリックリスナーを紐づける方法、またはGoogle Tag Managerの変数を使って特定の要素IDやCSSセレクタを識別・計測する方法で処理します。

以下のコード例はあくまで参考例です。そのまま使用せず、必ずご利用サイトの構成に合わせて調整してください。

例:AF Web SDKを使用してイベントを記録する

このメソッドは、[チェックアウト]ボタンや[ダウンロード]ボタンのクリックなど、ユーザーがページ上で行う特定のアクションを追跡する場合に使用します。

ユースケース:ECサイトを運営しており、ユーザーがショッピングカート内のCheckoutボタンをクリックした瞬間に、checkoutイベントを取得したい場合。

ネイティブユーザー操作の例:

<html>
<head>
    <script>
        window.onload = function () {
            document.getElementById('checkout').addEventListener('click', function () {
                AF('pba', 'event', {eventType: 'EVENT', eventValue: {'category' : 'holiday_promotion'}, eventName: 'checkout'});
            });
        }
    </script>
</head>
<body>
    <h1>Shopping Cart</h1>
    <button id='checkout'>Checkout</button>
</body>
</html>

How it works:

  1. ページが読み込まれると、スクリプトは checkout というIDを持つ要素にクリックイベントリスナーを設定します。
  2. ユーザーがボタンをクリックすると、コールバック関数が実行されます。
  3. この関数では、localStorageなどから関連データを取得し、AF() メソッドに渡すことができます。
  4. その後、SDKがcheckoutイベントをAppsFlyerプラットフォームへ送信します。
例:GTM経由でイベントを記録する

この方法では、GTMの組み込み変数とトリガーを使用して、Checkoutボタンのクリックなどの特定アクションを取得します。

1. checkoutページの設定

<html>
<head>
    <script>
        (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
        })(window,document,'script','dataLayer','GTM-XXXX');
    </script>
</head>
<body>
    <h1>Shopping Cart</h1>
    <button id='checkout'>Checkout</button>
</body>
</html>

2. GTM変数とトリガーの設定

  1. GTMで「Variables」>「Configure」をクリックし、Built-In Variablesリストで「Click Element」を有効にします。
  2. 新しいユーザー定義変数を作成します。 (変数のタイプ:すべての要素)
  3. 新しいトリガーを作成し、以下のとおり設定します:
    • トリガーのタイプ: クリック - すべての要素
    • このトリガーの発生場所: 一部のクリック
    • 条件: クリック要素がCSSセレクタ #checkout に一致する

3. インタラクションタグを作成する

  1. checkoutアクション用に、新しいCustom HTMLタグを作成します。
  2. 以下のインタラクションスクリプトを貼り付けます。

    <script>
      AF('pba', 'event', {eventType: 'EVENT', eventValue: {'category' : 'holiday_promotion'}, eventName: 'checkout'});
    </script>
  3. 前の手順で作成した「Checkout Click」トリガーを割り当てます。
イベント実装のベストプラクティス

データの正確性と正常な送信を担保するため、以下の技術要件を確認してください。

  • 読み込み順序:イベント呼び出しが行われる前に、Web SDKの関数タグがページスコープ内で完全に読み込まれていることを確認してください。
  • データ形式:イベント値には特殊文字を含めないでください。たとえば、収益には通貨記号を含めず、数値で指定してください($10.50 ではなく 10.50 を使用します)。
  • 文字数制限:event_value の文字列は簡潔にしてください。 4000文字を超える値は切り捨てられます。
  • Event deduplication: We recommend sending af_customer_event_id in eventValue, with a unique value per event. This matters most when you send the same event through both the Web SDK and the server-to-server (S2S) API. AppsFlyer forwards this value to the ad network, which uses it to deduplicate the server-side event it receives from AppsFlyer against the same event it received from its own pixel.
  • Revenue placement: Populate eventRevenue only on events where money actually moved, such as a purchase or a confirmed subscription. For events that carry a monetary value but aren't realized revenue (e.g., add to cart, initiated checkout, or content view), use af_price and af_currency in eventValue instead. Sending eventRevenue on both the checkout and the purchase double-counts revenue in every report.
  • Event naming: Don't add platform suffixes such as _web to event names. Platform is already a dimension in the dashboard and in raw data. Use the same event names as in your mobile app to keep cross-platform reporting unified.

6. カスタマーユーザーIDの設定

イベント計測の実装後は、setCustomerUserId を使用して永続的なユーザーIDを設定します。 これにより、Web上のアクティビティを他のプラットフォーム(モバイル、PC、CTV)と紐づけ、プラットフォームをまたいだユーザージャーニーを統合的に把握できます。

重要なルール

  • 一貫性:モバイルアプリ実装で使用しているCUIDと同じ値を使用してください(iOS、Android、Unityのモバイル向け setCustomerUserId を参照してください)。
  • 設定タイミング:CUIDは、ログイン後や新規登録後など、任意のタイミングで送信できます。 CUIDを取得でき次第、可能な限り早い段階で設定してください。多くの場合、ユーザーがログインまたは新規登録によって自身を識別するまで、CUIDを設定することはできません。
  • シンタックス:値は文字列として送信してください(引用符で囲みます)。例: AF('pba', 'setCustomerUserId', '663274')
  • プライバシー:メールアドレスや電話番号など、個人を特定できる情報(PII)は含めないでください。
例:サインアップ後にCUIDを設定する(ネイティブ)

これらの例で提供されているコードは参照専用です。このコードをそのまま使用しないでください。このコードの使用方法が不明な場合は、Web開発者に相談してください。

SDKが機能していることを確認:ブラウザのデベロッパーツールでネットワークコールを確認し、SDKがリクエストを送信していることを検証します。

ユーザーシナリオ:

  • ユーザーがWebサイトでサインアップします。
  • Webサイト側のコードがユーザー情報を取得し、サーバーへ送信します。
  • サーバーがユーザーに対して一意のCUIDを生成します。
  • サインアップ後のThank Youページで、新しいCUIDをサーバーに問い合わせます。
  • サーバーからのレスポンスを使用し、Web SDKの setCustomerUserId() メソッドでAppsFlyerのCUIDを設定します。

サインアップフォームの例

以下のコード例は、シンプルなサインアップフォームです。フォーム送信時にメールアドレスを localStorage に保存します。ユーザーがThank Youページに到達すると、そのメールアドレスがサーバーへ送信され、該当メールアドレスに対応する一意のCUIDを取得します。

<html>
<head>
    <script>
!function(t,e,n,s,a,c,i,o,p){t.AppsFlyerSdkObject=a,t.AF=t.AF||function(){
(t.AF.q=t.AF.q||[]).push([Date.now()].concat(Array.prototype.slice.call(arguments)))},
t.AF.id=t.AF.id||i,t.AF.plugins={},o=e.createElement(n),p=e.getElementsByTagName(n)[0],o.async=1,
o.src="https://websdk.appsflyersdk.com?"+(c.length>0?"st="+c.split(",").sort().join(",")+"&":"")+(i.length>0?"af_id="+i:""),
p.parentNode.insertBefore(o,p)}(window,document,"script",0,"AF","pba",{pba: {webAppId: "WEB_DEV_KEY"}})
    </script>
    <script>
        function storeUserEmail() {
            var userEmail = document.getElementById('email').value;
            localStorage.setItem('user_email', userEmail);
        }
    </script>
</head>
<body>
    <h1>Sign Up</h1>
    <form onsubmit="storeUserEmail()" action="/signup" method="post">
        <div><label>Name</label><input type="text" name="name" id="name"></div>
        <br/>
        <div><label>Email</label><input type="email" name="email" id="email"></div>
        <br/>
        <input type="submit" id="submit">
    </form>
</body>
</html>

Thank Youページの例

このコードではFetch APIを使用します。ユーザーが入力したメールアドレスをサーバーへ送信します。サインアップ時にサーバー側で一意のCUIDを持つユーザーが作成される前提で、メールアドレスをサーバーへ送信すると、一意のCUIDが返されます。サーバーから返された一意のCUIDが、setCustomerUserId メソッドに渡される値になります。

<html>
<head>
    <script>
!function(t,e,n,s,a,c,i,o,p){t.AppsFlyerSdkObject=a,t.AF=t.AF||function(){
(t.AF.q=t.AF.q||[]).push([Date.now()].concat(Array.prototype.slice.call(arguments)))},
t.AF.id=t.AF.id||i,t.AF.plugins={},o=e.createElement(n),p=e.getElementsByTagName(n)[0],o.async=1,
o.src="https://websdk.appsflyersdk.com?"+(c.length>0?"st="+c.split(",").sort().join(",")+"&":"")+(i.length>0?"af_id="+i:""),
p.parentNode.insertBefore(o,p)}(window,document,"script",0,"AF","pba",{pba: {webAppId: "WEB_DEV_KEY"}})
    </script>
    <script>
        window.onload = function () {
            var userEmail = localStorage.getItem('user_email');
            fetch('users/' + userEmail).then(function (res) {
                res.text().then(function (id) {
                    console.log(id);
                    AF('pba', 'setCustomerUserId', id);
                });
            });
        }
    </script>
</head>
<body>
    <h1>Thank You for Signing Up!</h1>
</body>
</html>
例:サインアップ後にCUIDを設定する(Google Tag Manager)
  1. サインアップページを設定します。

    以下は、シンプルなサインアップフォームのコード例です。フォーム送信時にメールアドレスを localStorage に保存します。ユーザーがThank Youページに到達すると、そのメールアドレスがサーバーへ送信され、該当メールアドレスに対応する一意のCUIDを取得します。

    <html>
    <head>
        <script>
            (function (w, d, s, l, i) {
                w[l] = w[l] || []; w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
                var f = d.getElementsByTagName(s)[0], j = d.createElement(s),
                    dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true;
                j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
                f.parentNode.insertBefore(j, f);
            })(window, document, 'script', 'dataLayer', 'GTM-5VJ6C7R');
            function storeUserEmail() {
                var userEmail = document.getElementById('email').value;
                localStorage.setItem('user_email', userEmail);
            }
        </script>
    </head>
    <body>
        <h1>Sign Up</h1>
        <form onsubmit="storeUserEmail()" action="/signup" method="post">
            <div><label>Name</label><input type="text" name="name" id="name"></div>
            <br />
            <div><label>Email</label><input type="email" name="email" id="email"></div>
            <br />
            <input type="submit" id="submit">
        </form>
    </body>
    </html>
  2. サインアップしたユーザー向けのThank Youページを設定します。以下のコードは、GTMトリガーを含むThank Youページの例です。 サインアップフォームでユーザーが入力したメールアドレスをサーバーへ送信します。サインアップ時にサーバー側で一意のCUIDを持つユーザーが作成される前提で、メールアドレスをサーバーへ送信すると、一意のCUIDが返されます。サーバーから返された一意のCUIDは、setCustomerUserId() メソッドを使用して送信されます。

    <script>
        window.onload = function () {
            var userEmail = localStorage.getItem('user_email');
            fetch('users/' + userEmail).then(function (res) {
                res.text().then(function (id) {
                    console.log(id);
                    AF('pba', 'setCustomerUserId', id);
                });
            });
        }
    </script>
  3. Thank Youページの読み込み後にサブスクリプションをアトリビューションするため、新しいタグを追加します。

    Adding a new GTM tag for the CUID conversion event
  4. タグにわかりやすい名前を付け、タグタイプとして「Custom HTML」を選択します。

    GTMで新しいタグを作成し、タグタイプとして「<strong>Custom HTML</strong>」を選択します。
    <script>
        var userEmail = localStorage.getItem('user_email');
        fetch('users/' + userEmail).then(function (res) {
            res.text().then(function (id) {
                console.log(id);
                AF('pba', 'setCustomerUserId', id);
            });
        });
    </script>
  5. 「Advanced Settings」>「Tag Sequencing」を展開し、メインのWeb SDK初期化タグの後に発火するよう設定されていることを確認してください。

    Configuring GTM Tag Sequencing for the conversion tag
  6. コンバージョンタグをいつ発火させるかを指定するため、コンバージョンタグにトリガーを設定します(以下の例では、「Thank you」ページの読み込み時に発火します)。

    <a href="#3-set-and-record-events">イベントの設定・記録:</a>ネイティブJavaScriptまたはGoogle Tag Managerを使用して、ページ読み込み時またはユーザー操作時にカスタムイベントを定義し、送信します。

7. プライバシーの管理

Following the implementation of event measurement, you may need to apply specific security and privacy constraints to comply with organizational or regional standards.

イベント送信をオプトイン/オプトアウトする

計測は以下2つの方法で制御できます。

SDKの初期状態設定(スニペット内)

Webページ初回読み込み時に、SDKがイベント送信を開始するか、明示的な指示があるまで待機するかを定義します。この設定はWebスニペット内で指定します。

  • イベント送信を有効化:{pba: {webAppId: "...", measurementStatus:true}}
  • イベント送信を無効化:{pba: {webAppId: "...", measurementStatus:false}}

measurementStatus が空、または NULL の場合、AppsFlyerは measurementStatus:true として扱います。

明示的な制御

明示的な制御は初期状態設定より優先され、永続的なファーストパーティCookieを使用します:

  • Webサイトドメイン上に設定されます。
  • Cookieの有効期限は、Web SDKまたはブラウザ設定に従います。
  • 常にブラウザのCookie設定の影響を受けます。

コマンド

  • イベント送信を開始する(オプトイン):window.AF_SDK.PLUGINS.PBA.enableMeasurement()
  • イベント送信を停止する(オプトアウト):window.AF_SDK.PLUGINS.PBA.disableMeasurement()
データを安全に管理・フィルタリングする

Webサイトで厳格なセキュリティ要件やデータプライバシー要件が求められる場合は、以下の仕組みを使用して、Web SDKが環境やデータとどのように連携するかを制御できます。

コンテンツ・セキュリティ・ポリシー(CSP)

WebサイトでCSPによるJavaScript保護を適用している場合、Web SDKはCSP設定および手順2で選択したスニペットに応じて、2種類の方法をサポートします。

  • CSPで self を使用する場合:script-src の許可リストに https://websdk.appsflyersdk.com を追加してください。これはスタンダードWeb SDKおよびアドバンスSDK検証の両方で利用できます。
  • CSPでnonceを使用する場合:ポリシーで script-src 'nonce-...' を使用している場合は、以下のアドバンスSDK検証向けのnonce対応版スニペットを使用してください。これにより、検証プロセスで必要となる3つのscriptタグすべてにnonceが引き継がれます。 {{CSP_NONCE}} を、サーバー側でリクエストごとに生成するnonce値へ置き換えてください。

以下の表は、nonce対応版スニペットと互換性のあるCSPポリシーを示しています。

ポリシー 動作可否 注意
script-src 'self' 任意 外部CDNオリジンが許可されず、インラインスクリプトもブロックされます。
script-src 'self' https://websdk.appsflyersdk.com 部分的 ローダーおよびSDKは許可されますが、インライン設定スクリプトはブロックされます。
script-src 'nonce-...' https://websdk.appsflyersdk.com Yes nonceによってインラインスクリプトとローダーが許可され、SDKタグにもnonceが引き継がれます。
script-src 'nonce-...' 'strict-dynamic' 可能 (推奨) nonceによってインラインスクリプトとローダーが許可され、strict-dynamic により動的に挿入されたSDKタグにも信頼が引き継がれます。許可リストへのCDNオリジン追加は不要です。
CSPポリシーの互換性

アドバンスSDK検証 + CSP nonce対応スニペット

Smart Bannersを使用しない場合
<script nonce="{{CSP_NONCE}}">
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" } };
  window.AF.plugins = {};

  // Manifest loader config — nonce forwarded to the injected SDK <script> tag
  window.AF_LOADER_CONFIG = {
    baseUrl: "https://websdk.appsflyersdk.com",
    plugins: ["pba"],
    nonce: "{{CSP_NONCE}}"
  };

  // Inject manifest loader
  var loaderScript = document.createElement("script");
  loaderScript.src = "https://websdk.appsflyersdk.com/manifestLoader.v1.js";
  loaderScript.integrity = "sha384-Uncl2YwvjFpFz0PwEfl3bL/0JsOQcDFEpwXHzcN0MBavn9vvFEx5pZxADTq8h+CV";
  loaderScript.crossOrigin = "anonymous";
  loaderScript.nonce = "{{CSP_NONCE}}";
  loaderScript.async = true;
  document.head.appendChild(loaderScript);
</script>
Smart Bannersを使用する場合
<script nonce="{{CSP_NONCE}}">
  // Queue — buffers AF() calls until the SDK is ready
  window.AppsFlyerSdkObject = "AF";
  window.AF = window.AF || function() {
    (window.AF.q = window.AF.q || []).push([Date.now()].concat(Array.prototype.slice.call(arguments)));
  };
  // Replace WEB_DEV_KEY with your Web SDK ID
  window.AF.id = window.AF.id || { pba: { webAppId: "WEB_DEV_KEY" }, banners: { key: "YOUR_BANNER_KEY" } };
  window.AF.plugins = {};

  // Manifest loader config — nonce forwarded to the injected SDK <script> tag
  window.AF_LOADER_CONFIG = {
    baseUrl: "https://websdk.appsflyersdk.com",
    plugins: ["banners", "pba"],
    nonce: "{{CSP_NONCE}}"
  };

  // Inject manifest loader
  var loaderScript = document.createElement("script");
  loaderScript.src = "https://websdk.appsflyersdk.com/manifestLoader.v1.js";
  loaderScript.integrity = "sha384-Uncl2YwvjFpFz0PwEfl3bL/0JsOQcDFEpwXHzcN0MBavn9vvFEx5pZxADTq8h+CV";
  loaderScript.crossOrigin = "anonymous";
  loaderScript.nonce = "{{CSP_NONCE}}";
  loaderScript.async = true;
  document.head.appendChild(loaderScript);
</script>

クエリパラメータを破棄する

URLクエリパラメータに機密情報が含まれる場合、AppsFlyerに対してクエリパラメータ(URL、referrer、header_referer)を破棄するよう指示できます。

  • すべてのクエリパラメータを破棄する場合:af_url=trueを追加
  • 特定のパラメータのみを破棄する場合:af_url_mask=paramを使用(複数のパラメータを指定する場合は;で区切る)

例:

  • 元のURL:param1=value1&param2=value2&param3=value3&af_url_mask=param2;param3
  • 結果:param1=value1&af_url_mask=param2;param3

Web SDK Cookieリファレンス

Web SDKは、以下のCookieを設定または使用します。

Cookie名 ドメイン Lifespan 使用タイミング 詳細
afUserId お客様のWebサイトのドメイン 395日 非AMP(Accelerated Mobile Pages)環境 Webページの読み込みおよびナビゲーションイベントにおいて、ユーザー識別に使用されます。
AF_SYNC お客様のWebサイトのドメイン 1週間 非AMP(Accelerated Mobile Pages)環境 最終的なユーザー識別子が設定済みであることを示します。サイトの読み込み時間短縮に使用されます。
af_id appsflyer.com 395日 Non-Accelerated Mobile Pages when third-party cookies are permitted アプリ起動およびナビゲーションイベントにおいて、ユーザー識別に使用されます。
af_id onelink.me 395日 Non-Accelerated Mobile Pages when third-party cookies are permitted Link BannerやOneLink経由のエンゲージメント、またはその両方を、アプリ起動イベントへ紐づけます。
amp-afUserid AMP CDNまたはお客様のWebサイトのドメイン 1年 Accelerated Mobile Pages
AF_DEFAULT_MEASUREMENT_STATUS お客様のWebサイトのドメイン 395日 非AMP(Accelerated Mobile Pages)環境 同意状態を保存します。ユーザーが同意するまでSDKの動作を停止します。デフォルトでは設定されません。同意管理(consent gating)を設定している場合のみ使用されます。