How can we help?

对接AppsFlyer Web SDK

  • 更新

概览:在网站中安装AppsFlyer Web SDK(也称为Pixel),向AppsFlyer上报用户访问和事件,并设置长期有效的客户用户ID(CUID),统一跨平台用户旅程。

概览

Web SDK可记录访客与网站的互动情况,并将相关信息发送至AppsFlyer。Web SDK是一个40–60KB的插件模块,可将用户访问和在网站上的操作上报至AppsFlyer平台。

按照以下步骤完成Web SDK对接,包括安装、验证和隐私控制。

  1. 获取密钥。获取Web SDK ID(也称为Web Dev Key)。
  2. 选择代码片段。根据对接类型和安全要求选择相应的代码片段。
  3. 部署Web SDK。使用原生代码片段、Google Tag Manager或Adobe Launch Tag Manager部署SDK。
  4. 确认SDK正常运行。在浏览器开发者工具中检查网络调用,确认SDK能够发送请求。
  5. 设置和记录事件。使用原生JavaScript或Google Tag Manager定义自定义事件,并在页面加载或用户互动时发送事件。
  6. 设置客户用户ID。设置长期有效的CUID,将网页端与其他平台的用户活跃数据统一关联。
  7. 管理隐私。控制用户是否参与效果衡量,并配置安全和数据过滤功能(内容安全策略和丢弃查询参数)。
  8. Web SDK Cookie说明。查看Web SDK设置或使用的Cookie,包括用途、有效期和作用域。

1获取密钥

获取Web SDK ID(也称为Web Dev Key):

  1. 在AppsFlyer顶部菜单中,打开应用设置
  2. 在页面顶部的应用选择器中,选择您的网页端应用(即以「website-」为前缀的网站域名)。
  3. SDK身份验证下,复制Web SDK ID

获取智能横幅密钥(如有需要):

  1. 在AppsFlyer侧边菜单中,打开互动>Web to App>智能横幅
  2. 复制所需的智能横幅密钥。

2选择代码片段

根据对接类型和安全要求选择相应的代码片段。有以下两种方案:

  • 标准Web SDK:标准对接方案。
  • 高级SDK验证:增强型对接方案,可为Web SDK提供供应链防护。使用该方案可加强安全防护,防范CDN遭入侵、DNS劫持和中间人攻击。

重要!

如果要从标准Web SDK迁移至高级SDK验证,请使用新代码片段替换现有代码片段。不要在现有代码片段的基础上再添加新代码片段。

标准Web SDK

使用此代码片段部署标准Web SDK对接方案。在所有需要加载SDK的页面中,将代码片段粘贴到标签内靠近开头的位置。

不使用智能横幅

<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>

使用智能横幅

<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劫持和中间人攻击。
  • SDK加载时间延长约250毫秒。

高级SDK验证为可选功能。标准对接方案仍受到全面支持,也是第三方分析追踪代码的行业标准。高级SDK验证可在此标准的基础上再提供一层防护。

如果您的网站使用nonce实施内容安全策略(CSP),请参阅「管理隐私」部分的内容安全策略(CSP),了解此代码片段支持nonce的扩展版本。

不使用智能横幅

<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>

使用智能横幅

<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。

方式A:直接添加到您的网站

在所有页面中执行以下操作:

  1. 在第2步的代码片段中,将WEB_DEV_KEY替换为您的Web SDK ID(如适用,还需替换YOUR_BANNER_KEY)。
  2. 将代码片段粘贴到网站标签内靠近开头的位置。

方式B:通过Google Tag Manager(GTM)部署

使用GTM优先级设置,让SDK在页面加载后尽快加载;每次加载页面时,只加载一次SDK。

  1. 打开Google Tag Manager。
  2. 新建AppsFlyer Web SDK代码。
  3. 选择自定义HTML代码类型。
  4. 为代码指定一个清晰易懂的名称。
  5. 将第2步中的代码片段粘贴到代码配置中。
  6. 点击保存
  7. 添加触发器:
    • 针对所有网页:
      1. 点击添加触发器
      2. 选择所有网页
      3. 点击保存
      4. 输入代码名称,然后点击保存
    • 针对特定网页:
      1. 点击保存代码
      2. 在GTM主窗口中,选择触发器。点击新建
      3. 点击铅笔图标。
      4. 选择网页浏览触发器类型。
      5. 选择某些网页浏览
      6. 根据需要设置网页和触发条件。
      7. 点击保存
      8. 将触发器与AppsFlyer Web SDK代码关联:
        1. GTM主窗口中,选择代码
        2. 选择之前创建的代码。
        3. 在触发条件面板中,点击铅笔图标。
        4. 选择之前创建的网页浏览触发器。
        5. 点击保存

注意

GTM自定义模板不支持高级SDK验证,因为其沙盒环境不允许设置验证所需的integrity属性。请改用自定义HTML代码类型。

方式C:通过Adobe Launch Tag Manager部署

在Adobe Experience Cloud中创建属性

  1. 打开Adobe Experience Cloud>Launch。
  2. 在Adobe Experience Cloud Launch中,点击转到Launch
  3. 点击新建属性
  4. 输入属性名称。
  5. 平台下,选择网页端
  6. 输入网站域名。
  7. 点击保存

将代码片段添加到Adobe Launch属性

  1. 我的网页端属性页面中,选择规则选项卡。
  2. 输入规则名称。建议名称:加载Web SDK。
  3. 如果部分的事件下,点击添加
    • 事件类型下,选择Core–DOM已就绪
    • 点击保留更改
  4. 然后部分的操作下,点击添加
    • 操作类型下,选择自定义代码
    • 选择JavaScript>打开编辑器,然后粘贴第2步中的代码片段(不要包含任何外层封装代码行)。
    • 点击保留更改,关闭代码编辑器。
  5. 点击保存

将Adobe Launch标签添加到网站

  1. 我的网页端属性页面中,选择环境选项卡。
  2. 找到要发布的环境所在行(开发或生产环境)。
  3. 安装列中,点击相应行的方框图标。
  4. 网页端安装说明对话框中,复制脚本代码片段并关闭对话框。
  5. 将代码片段粘贴到网站的head部分。

发布Adobe Launch环境

  1. 我的网页端属性页面中,前往发布选项卡。
  2. 开发部分下,点击添加新库
    • 输入库名称并选择环境。
    • 资源更改下,点击添加资源
    • 点击规则>加载Web SDK>最新>选择并创建新修订版本
    • 点击保存
  3. 开发部分下:
    • 点击新建库旁的操作菜单(三点图标),然后选择生成到开发环境
    • 再次点击操作菜单,然后选择提交以供审批
  4. 已提交部分下:
    • 点击操作菜单,然后选择生成到暂存环境
    • 再次点击操作菜单,然后选择批准发布
  5. 已批准部分下:
    • 点击操作菜单,然后选择生成并发布到生产环境

2确认SDK正常运行

安装后,在浏览器开发者工具中检查网络请求,确认SDK能够发送请求。

开发者工具截图

按照以下步骤确认SDK是否正常运行:

  1. 打开网站。
  2. 打开浏览器开发者工具。
  3. 前往(A)网络选项卡。
  4. 刷新页面。
  5. 按(B)appsflyer筛选。可能会显示两个请求:
    • SDK加载器——请求URL以https://websdk.appsflyersdk.com开头。这表示SDK脚本已正确加载。
    • 事件数据——请求URL以https://wa.appsflyer.com/events开头。这表示SDK正在向AppsFlyer发送事件数据。
  6. 选择(C)events请求(即wa.appsflyer.com调用)。
  7. 在「标头」下,确认(D)以下信息:
    • 请求URL以https://wa.appsflyer.com/events?site-id=开头。
    • site_id查询参数=WEB_SDK_KEY
    • 状态码为200。
  8. 确认site_id与AppsFlyer顶部菜单中我的应用下的WEB_SDK_KEY一致。
  9. 确认SDK只加载一次。多次加载SDK可能会导致SDK停止运行。

3设置和记录事件

初始化Web SDK后,即可在衡量基本访问数据的基础上,进一步采集具体的用户操作。本节将介绍如何使用原生JavaScriptGoogle Tag Manager定义和记录购买、注册等自定义事件。

设置事件

事件是网页端效果衡量的基础,用于表示对您业务具有价值的具体用户操作。要记录这些互动,需为每个事件定义相应的逻辑和参数,并正确地将收入、自定义元数据等事件参数传递至AppsFlyer平台。

事件示例(包含相关收入的购买事件)

AF('pba', 'event', {eventType: 'EVENT', eventName: 'purchase', eventRevenue: 12, eventValue: {"key1": 123, "key2": "name"}});

Web SDK事件参数表

参数名称 必填 说明
eventType 事件类型。格式:字符串。此参数必须始终填入EVENT。示例:eventType: "EVENT"
eventName 事件名称。格式:字符串。示例:Purchase、Subscription
eventRevenue 分配给转化事件的收入。格式:浮点数
eventRevenueCurrency 收入币种。3位ISO 4217货币代码。默认值:USD。格式:字符串
eventValue 描述事件的事件参数映射。使用此参数可发送产品SKU、商品明细价格等富应用内事件数据。格式:JSON。示例:{"sku": "ABC123", "color": "blue", "unit_price": 3.99, "currency": "USD"}限制:1000个字符。请勿超过此限制,否则超出部分将被截断。

页面加载时记录事件

对于最终跳转至感谢页面或确认页面的转化,通常采用这种方式记录事件。

您可以通过以下任一方式实现该触发器:在原生JavaScript中添加窗口加载方法,或在Google Tag Manager中配置网页浏览触发器。

警告

以下代码示例仅用于说明。请勿直接使用此代码;请根据网站的具体结构进行调整。

示例:通过AF Web SDK记录事件

这种方式适合记录通过页面跳转完成的转化,例如用户订阅邮件简报后进入感谢页面。

使用场景:用户完成邮件简报订阅后,页面跳转至确认页面。您希望确认页面显示后立即记录subscription事件。

原生页面加载示例:

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

运行方式:

  1. 页面会加载必要内容。
  2. 窗口完全加载后(window.onload),脚本会自动调用AF()方法。
  3. subscription事件及其相关元数据(category和label)会直接发送至AppsFlyer。

示例:通过GTM记录事件

这种方式会在「感谢」页面加载时触发代码,从而记录邮件简报订阅等成功转化。

1设置「感谢」页面

以下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中新建代码,并选择自定义HTML代码类型。
  2. 输入一个易于区分的名称(例如「AF Subscription Event」)。
  3. 将以下脚本粘贴到HTML文本区域:

    AF('pba', 'event', {eventType: 'EVENT', eventValue: {'category' : 'holiday_promotion'}, eventName: 'subscription'});
  4. 展开高级设置>代码排序。将此代码配置为在Web SDK主初始化代码触发后运行。
  5. 为此代码设置触发器,使其在「感谢」页面发生网页浏览时触发。

用户互动时记录事件

使用这种方式追踪无需重新加载页面的操作(点击按钮、下载、添加到购物车)。

通常可通过以下方式处理此类互动:为原生HTML元素绑定点击监听器,或使用Google Tag Manager变量,根据特定元素ID或CSS选择器识别并衡量互动。

警告

以下代码示例仅用于说明。请勿直接使用此代码;请根据网站的具体结构进行调整。

示例:通过AF Web SDK记录事件

使用此方法追踪用户在页面上的具体操作,例如点击结账下载按钮。

使用场景:您经营一个电商网站,希望用户点击购物车中的结账按钮时,立即采集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>

运行方式:

  1. 页面加载时,脚本会为ID为checkout的元素添加click事件监听器。
  2. 用户点击按钮后,系统会触发回调函数。
  3. 该函数可以获取相关数据(例如从localStorage中获取),并传递至AF()方法。
  4. 随后,SDK会将checkout事件发送至AppsFlyer平台。

示例:通过GTM记录事件

此方法使用GTM的内置变量和触发器,采集点击结账按钮等具体操作。

1设置结账页面

<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中,点击变量>配置,然后在内置变量列表中启用点击元素
  2. 新建一个用户定义的变量(类型:所有元素)。
  3. 新建触发器
    • 触发器类型:点击–所有元素
    • 此触发器的触发条件:某些点击
    • 条件:点击元素与CSS选择器#checkout匹配。

3创建互动代码

  1. 为结账操作新建自定义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个字符的值将被截断。

4设置客户用户ID

完成事件衡量配置后,使用setCustomerUserId设置长期有效的身份标识,将网页端活跃数据与移动端、PC和CTV等其他平台关联,统一查看用户的跨平台旅程。

主要规则

  • 一致性:CUID值应与移动应用配置中使用的值一致(有关移动端setCustomerUserId,请参阅iOSAndroidUnity)。
  • 设置时机:您可以在任意阶段发送CUID,例如用户登录或注册后。获取CUID后,应尽早完成设置。通常需要等到用户登录或注册并表明身份后,才能获取CUID。
  • 语法:以字符串形式发送该值(使用引号括起)。示例:AF('pba', 'setCustomerUserId', '663274')
  • 隐私:请勿包含邮箱地址或电话号码等个人身份信息(PII)。

示例:注册后设置CUID(原生代码)

以下示例中的代码仅供参考。请勿直接使用此代码。如果不确定如何使用,请咨询网站开发人员。

前提条件:发送事件前,页面已加载Web SDK;请勿重复加载。

用户场景:

  • 用户在网站中注册。
  • 网站代码收集用户信息并发送至服务器。
  • 服务器为用户生成唯一CUID。
  • 用户进入注册完成后的感谢页面后,网站会向服务器查询新CUID。
  • 根据服务器返回的响应,使用Web SDK的setCustomerUserId()方法设置AppsFlyer CUID。

注册表单示例

以下代码是一个简单的注册表单。提交表单后,邮箱地址会存储在localStorage中。用户进入感谢页面后,系统会将其邮箱地址发送至服务器,以获取该邮箱地址对应的唯一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>

感谢页面示例

该代码使用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中。用户进入感谢页面后,系统会将其邮箱地址发送至服务器,以获取该邮箱地址对应的唯一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. 为完成注册的用户设置感谢页面。以下代码用于感谢页面,其中的GTM触发器会将用户在注册表单中填写的邮箱地址发送至服务器。假设服务器会在用户注册时创建用户并生成唯一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. 添加一个新代码,用于在感谢页面加载后归因订阅事件。

  4. 为代码指定一个易于区分的名称,并选择自定义HTML代码类型。

    <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. 展开文本区域下方的高级设置代码排序,并将其配置为在此代码执行后触发转化。

  6. 为转化代码设置触发器,指定转化代码的触发时机(以下示例会在「感谢」页面加载时触发)。

5管理隐私

完成事件衡量配置后,您可能还需要根据组织或地区标准设置特定的安全与隐私限制。

选择是否发送事件

您可以通过以下两种方式控制效果衡量:

SDK初始状态设置(在代码片段中)

用于决定网页首次加载时,SDK是立即发送事件,还是等到您明确发出指令后再开始发送。此设置在网页端代码片段中定义。

  • 发送事件:{pba: {webAppId: "...", measurementStatus:true}}
  • 不发送事件:{pba: {webAppId: "...", measurementStatus:false}}

注意

如果measurementStatus为空或值为NULL,AppsFlyer会按measurementStatus:true处理。

显式控制

显式控制的优先级高于初始状态设置,并通过第一方Cookie持续保存设置:

  • Cookie设置在您的网站域名下。
  • Cookie会在Web SDK或浏览器设定的期限后过期。
  • Cookie始终受浏览器Cookie设置限制。

命令

  • 开始发送事件(选择发送):window.AF_SDK.PLUGINS.PBA.enableMeasurement()
  • 停止发送事件(选择不发送):window.AF_SDK.PLUGINS.PBA.disableMeasurement()

数据安全与过滤

如果网站需要遵循严格的安全或数据隐私协议,请使用以下机制配置Web SDK与运行环境及数据的交互方式。

内容安全策略(CSP)

如果网站要求通过CSP保护JavaScript,Web SDK可根据您的CSP配置和第2步所选的代码片段采用以下两种方案。

  • 使用self的CSP:将https://websdk.appsflyersdk.com添加到script-src允许列表中。标准Web SDK和高级SDK验证均支持这种方式。
  • 使用nonce的CSP:如果您的策略使用script-src 'nonce-...',请使用下方支持nonce的高级SDK验证扩展版本。该版本会将nonce传递给验证流程所需的全部3个脚本标签。将{{CSP_NONCE}}替换为服务器针对每个请求生成的nonce值。

下表列出了与nonce扩展版本兼容的CSP策略。

策略 是否支持 说明
script-src 'self' 不允许外部CDN源;内联脚本也会被阻止。
script-src 'self' https://websdk.appsflyersdk.com 部分支持 允许加载器和SDK,但内联设置脚本仍会被阻止。
script-src 'nonce-...' https://websdk.appsflyersdk.com nonce涵盖内联脚本和加载器;加载器会将nonce转发至SDK脚本标签。
script-src 'nonce-...' 'strict-dynamic' 是(推荐) nonce涵盖内联脚本和加载器;strict-dynamic会将信任传递给动态注入的SDK脚本标签。无需将CDN源添加到允许列表。
CSP策略兼容性

使用CSP nonce的高级SDK验证代码片段

不使用智能横幅

<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>

使用智能横幅

<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、引荐来源网址和header_referer中的查询参数。

  • 丢弃所有查询参数:附加af_url=true
  • 丢弃特定查询参数:使用af_url_mask=param(使用;分隔多个参数)

示例:

  • 原始值: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名称 域名 有效期 使用场景 说明
afUserid 您的网站域名 395天 非AMP页面 用于在网页加载和导航事件中识别用户。
AF\_SYNC 您的网站域名 1周 非AMP页面 表示已设置最终用户标识符。用于缩短网站加载时间。
af\_id appsflyer.com 395天 允许第三方Cookie的非AMP页面 用于在应用启动和导航事件中识别用户。
af\_id onelink.me 395天 允许第三方Cookie的非AMP页面 将链接横幅互动、OneLink互动或两者与应用启动事件关联。
amp-afUserid AMP CDN或您的网站域名 1年 AMP页面
AF\_DEFAULT\_MEASUREMENT\_STATUS 您的网站域名 395天 非AMP页面 存储用户同意状态。在用户同意前阻止SDK运行。默认不设置。仅在配置用户同意控制后使用。

This article was translated using AI and may contain errors. For the most accurate information, please refer to the English version using the language selector.


Share article: