# 收集玩家数据

Pushwoosh 需要知道您的玩家是谁，以及他们在游戏中做了什么。事件记录玩家的操作，标签保存每位玩家的当前状态。

<Aside type="tip" title="让 AI Assistant 创建事件和标签">
[AI Assistant](/zh/product/pushwoosh-ai/ai-assistant/) 可以在您的应用中创建本页列出的事件和标签。将本页链接发送给它，并要求它将标签设为 User-specific。在批准每项更改之前先检查一遍。
</Aside>

<span id="identify-players-by-user-id" />

## 通过 User ID 识别玩家

<Aside type="caution" icon="setting" title="需要开发者协助">
设置 User ID 需要修改游戏代码。请将[收集 User ID](/zh/developer/first-steps/collecting-user-ids/#setuserid-sdk-method) 分享给您的开发人员。
</Aside>

Pushwoosh 会将一位玩家的所有设备关联到同一个 User ID，因此您的细分和 Journey 会把一个人当作一位玩家。玩家登录之前设备记录的事件和 User-specific 标签会保留在设备之前的 ID 上。Device-specific 标签随设备迁移。

默认情况下，Pushwoosh 使用每台设备的硬件 ID（HWID）作为其 User ID。这样，一位在两台设备上玩游戏的玩家会被算作两位玩家。为避免登录玩家出现这种情况，请将您自己的账户 ID 设置为他们的 User ID：

1. 选择要使用的 ID。使用游戏已为每位玩家分配的账户 ID。
2. 请开发人员在玩家登录时使用该 ID 调用 `setUserId`。
3. 检查结果。在测试设备上登录游戏，然后打开 **受众** → **用户探索器**，按 **用户 ID** 搜索并输入账户 ID。随即会打开该玩家的资料。

从不登录的玩家保留 HWID 作为其 User ID，由 Pushwoosh 为他们设置。

要详细了解 User ID 与设备之间的关系，请参阅[用户 (User ID)](/zh/product/pushwoosh-knowledge-hub/users-userids/)。

<span id="set-up-the-events-to-track" />

## 设置要跟踪的事件

事件是 Pushwoosh 了解玩家行为的方式。请先创建事件：[细分](/zh/tutorials/industry-playbooks/mobile-games/build-the-segments/)按玩家触发的事件对玩家进行分组，而 [Journey](/zh/tutorials/industry-playbooks/mobile-games/build-the-journeys/) 会在某个事件发生时启动。

在构建任何内容之前，先规划好事件及其属性。[游戏应用推荐事件](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/)列出了带有属性的现成游戏事件，[自定义事件](/zh/product/audience-data-and-segmentation/events/custom-events/)介绍了如何定义您自己的事件。

事件分为两类：

* [默认事件](#default-events)：设备注册、应用打开、购买等。SDK 会发送这些事件，您无需在控制面板中创建它们。
* [自定义事件](#custom-events)：关卡完成、领取奖励、打开商店等。您的开发人员[从游戏发送这些事件](#send-the-events-from-the-game)，Pushwoosh 会在每个事件首次到达时创建它。如果要自行选择属性类型，请先在控制面板中创建该事件。请参阅[自定义事件](/zh/product/audience-data-and-segmentation/events/custom-events/)和[自动创建的事件](/zh/product/audience-data-and-segmentation/events/#events-created-automatically)。

<span id="default-events" />

### 默认事件

SDK 会为您发送这些事件。本实战手册中的大多数 Journey 都需要它们：新手引导、召回和购买优惠。

* [`PW_DeviceRegistered`](/zh/product/audience-data-and-segmentation/events/default-events/#pw_deviceregistered)：设备收到了第一个推送令牌。只有当游戏调用 `registerForPushNotifications` 时，SDK 才会请求令牌；在 iOS 上，该调用还会显示权限提示，并且无论玩家如何回答，令牌都会到达。如果游戏在首次启动之后才请求权限，该事件会在那一刻触发，而不是在安装时触发。要捕获新玩家，请改用 `Tutorial started` 事件。
* [`PW_ApplicationOpen`](/zh/product/audience-data-and-segmentation/events/default-events/#pw_applicationopen)：玩家打开了游戏。您需要用它来找出仍在玩的玩家和已停止玩的玩家，以便召回他们。
* [`PW_InAppPurchase`](/zh/product/audience-data-and-segmentation/events/default-events/#pw_inapppurchase)：玩家在游戏中购买了物品。您需要用它来区分付费玩家和未付费玩家，例如只向从未付费的玩家提供首购优惠。在 iOS SDK 中，开发人员可以开启购买跟踪或从代码发送购买事件；在 Android 上，他们始终从代码发送。在 iOS 上，该事件仅针对在 App Store Connect 中配置的产品触发。
* 可选：[`PW_UserIdle`](/zh/product/audience-data-and-segmentation/events/default-events/#pw_useridle)：当玩家在您设定的时间内（至少 30 秒）没有触摸屏幕时触发。它会启动一个 Journey，在玩家卡住时显示 In-App 提示。开发人员需要在 SDK 配置中启用它。
* 可选：[`PW_ApplicationExit`](/zh/product/audience-data-and-segmentation/events/default-events/#pw_applicationexit)：当玩家离开游戏并且在 10 到 30 秒内没有返回时触发。它会为中途离开的玩家启动召回 Journey。开发人员需要在 SDK 配置中启用它。

SDK 首次发送某个事件后，该事件会出现在 **受众** → **事件** 中。

如果要提前将其他默认事件添加到列表中，例如在游戏更新上线之前构建细分：

1. 打开 **受众** → **事件**，然后点击 **创建事件**。
2. 选择 **默认事件**。
3. 选择该事件并点击 **激活**。

第 3 步中的列表不包括 `PW_UserIdle` 和 `PW_ApplicationExit`。只有在 SDK 首次发送它们之后，它们才会出现在 **受众** → **事件** 中。


有关这些及其他默认事件的详细信息，请参阅[默认事件](/zh/product/audience-data-and-segmentation/events/default-events/)。

<span id="custom-events" />

### 自定义事件

自定义事件记录游戏中发生的事情，例如完成一个关卡。您选择游戏需要哪些事件，开发人员负责发送，您负责检查它们是否到达。

<span id="choose-the-events-to-track" />

#### 选择要跟踪的事件

选择游戏需要的事件以及每个事件携带的属性，例如 `Level completed` 的 `level_id`。下表提供了一些示例：您可以直接使用、重命名，或添加您自己的事件。只跟踪您要启动的 Journey 所需的事件。

| 事件 | 触发时机 | 关键属性 | 用途 |
| --- | --- | --- | --- |
| [New level](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/#new-level) | 玩家达到新关卡 | `level_id` (String) | 可选：您自己的里程碑细分 |
| [Level completed](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/#level-completed) | 玩家完成一个关卡 | `level_id` (String) | 活跃未付费玩家和卡关玩家细分、卡关玩家帮助 Journey |
| Level failed | 玩家关卡失败 | `level_id` (String) | 卡关玩家细分和 Journey |
| Tutorial started | 玩家开始游戏内新手教程 | `tutorial_name` (String) | 新手引导 Journey、教程流失玩家细分 |
| [Tutorial completed](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/#tutorial-completed) | 玩家完成游戏内新手教程 | `tutorial_name` (String), `completion` (Boolean) | 新手引导 Journey、推送权限流程 |
| [Virtual currency earned](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/#virtual-currency-earned) | 玩家的游戏内货币余额增加 | `currency_name` (String), `quantity` (Integer) | 可选：您自己的基于货币的细分 |
| [Achievement unlocked](/zh/product/audience-data-and-segmentation/events/recommended-events-for-gaming-apps/#achievement-unlocked) | 玩家解锁一项成就 | `achievement_name` (String), `level` (Integer) | 成就猎人细分 |
| Daily reward claimed | 玩家领取每日奖励 | `day_number` (Integer) | 每日奖励提醒 Journey |
| Live event joined | 玩家加入限时活动 | `event_id` (String) | 限时活动 Journey 的转化目标 |
| Store opened | 玩家打开游戏内商店 | `section` (String) | 商店放弃 Journey |

<Aside type="tip" title="您的游戏没有新手教程？">
在本实战手册提到 `Tutorial started` 和 `Tutorial completed` 的所有地方，改用您自己的事件来表示每位新玩家最先完成的两个操作，例如开始和完成第一个关卡。

* 第一个事件启动新手引导 Journey，第二个事件告诉它玩家已完成。跳过与 `Tutorial completed` 配套的 `completion` 条件。
* SDK 本身不发送首次启动事件，因此这两个事件都必须是由游戏发送的自定义事件。
</Aside>

<span id="send-the-events-from-the-game" />

#### 从游戏发送事件

<Aside type="caution" icon="setting" title="需要开发者协助">
发送事件需要修改游戏代码。请将[面向开发者的事件](/zh/developer/guides/audience-and-segmentation/events/)和[游戏事件示例](/zh/developer/guides/audience-and-segmentation/events/custom-events-examples#gaming-apps)分享给您的开发人员。他们会在操作发生的那一刻使用 `postEvent` 发送每个事件。购买和奖励发放应由游戏服务器携带玩家的 `userId` 发送。
</Aside>

与开发人员商定游戏发送哪些事件，以及每个事件携带哪些属性。事件和属性的名称必须完全一致。

例如，游戏这样发送带有 `level_id` 属性的 `Level completed`：

<Tabs>
<TabItem label="Android">
```java
TagsBundle attributes = new TagsBundle.Builder()
    .putString("level_id", "12")
    .build();

InAppManager.getInstance().postEvent("Level completed", attributes);
```
</TabItem>
<TabItem label="iOS">
```swift
PWInAppManager.shared().postEvent("Level completed", withAttributes: ["level_id": "12"])
```
</TabItem>
</Tabs>

如果事件发生在已经发送自有 Webhook 的服务器上，例如您的游戏后端或锦标赛服务，它可以通过[入站 Webhook](/zh/product/integrations/inbound-webhook/) 而不是 `postEvent` 到达 Pushwoosh。您在控制面板中将其发送的字段映射到 Pushwoosh 事件，该事件就可以像其他事件一样启动 Journey。

要检查事件是否到达，请打开 **受众** → **用户探索器**，找到一位测试玩家，然后打开 **事件历史** 选项卡。


<span id="track-revenue-as-pw_conversion" />

### 以 PW_Conversion 跟踪收入

`PW_Conversion` 以统一格式记录每笔购买的金额和货币。Journey 中的收入目标以及 [RFM 分群](/zh/product/audience-data-and-segmentation/segmentation/rfm-segmentation/)中的消费层级都需要它，RFM 分群会按玩家最近一次购买的时间、购买频率和消费金额对玩家进行分组。

iOS SDK 跟踪的购买会自动进入 `PW_Conversion`，因为它们带有 `__amount` 和 `__currency` 属性。来自 Android 的购买需要以下方式之一：

* 如果您的游戏同时在 iOS 和 Android 上运行，请让开发人员通过 `postEvent` 将 Android 购买作为带有数值型 `__amount` 和 `__currency` 属性的 `PW_InAppPurchase` 发送，而不是使用 SDK 的购买方法。这样，同一个自动映射就能覆盖两个平台。
* 如果您的游戏只在 Android 上运行，请自行映射购买，无需编写新代码。一个事件只保留一个映射，因此在有 iOS 购买的游戏中，手动映射会替换自动映射。

要自行映射购买：

1. 打开 **受众** → **事件**，然后打开转化事件设置。
2. 将 `PW_InAppPurchase` 添加为转化事件。
3. 选择保存其 **价格** 和 **货币** 的属性。
4. 点击 **应用**。

<Aside type="caution">
每笔交易只使用一种方式。如果您的代码还为同一笔购买发送 `PW_Conversion`，Pushwoosh 会记录两个独立的转化事件。
</Aside>

有关所有设置选项，请参阅[转化事件](/zh/product/audience-data-and-segmentation/events/conversion-events/)。

<span id="track-subscriptions-from-the-stores" />

### 跟踪来自应用商店的订阅

如果您的游戏销售订阅，例如 VIP 通行证或战斗通行证，Pushwoosh 会从 App Store 和 Google Play 接收其状态变更。每次变更都会以 `PW_Subscription*` 事件的形式到达，例如：

* `PW_SubscriptionStart`：玩家订阅。
* `PW_SubscriptionCancel`：玩家关闭自动续订。
* `PW_SubscriptionBillingIssue`：续订付款失败。

使用这些事件启动 Journey，例如在已取消的通行证到期前发送提醒。

<Aside type="caution" icon="setting" title="需要开发者协助">
游戏必须在每次购买时传递玩家的 Pushwoosh HWID：

* 在 iOS 上，作为 `appAccountToken` 传递。
* 在 Android 上，作为 `obfuscatedAccountId` 传递。游戏传递 SDK 的 `getSubscriptionAccountId()` 的值，即 Application Code 与 HWID 的组合，而不是单独的 HWID。

如果没有它，Pushwoosh 会收到通知，但不会记录任何事件，之前购买的订阅以后也无法匹配。请将 [App Store 订阅跟踪](/zh/product/integrations/app-store-subscription-tracking/)和 [Google Play 订阅跟踪](/zh/product/integrations/google-play-subscription-tracking/)分享给您的开发人员。
</Aside>

这些事件仅涵盖订阅。一次性购买（例如金币礼包）仍以 `PW_InAppPurchase` 的形式到达。

<span id="store-player-data-in-tags" />

## 将玩家数据存储在标签中

[标签](/zh/product/audience-data-and-segmentation/user-data-tags/)是 Pushwoosh 存储在玩家资料中的值，例如玩家的关卡或玩家是否付过费。事件记录发生了什么，标签保存当前状态。标签可以帮助您：

* 只向具有特定值的玩家发送消息，例如只向付费玩家发送优惠。
* 将该值放入消息文本中，例如玩家的关卡。请参阅[构建 Journey](/zh/tutorials/industry-playbooks/mobile-games/build-the-journeys/)。

标签是可选的。本实战手册中的 Journey 基于事件和 Pushwoosh 自行设置的默认标签运行，因此您一开始可以不设置自己的标签。当您需要更多方式对玩家分组时再添加它们。请参阅[按标签划分的细分](/zh/tutorials/industry-playbooks/mobile-games/build-the-segments/#segments-by-tags)。

### 您自己的标签

开发人员从游戏发送标签值，您也可以[从 CSV 文件导入](/zh/product/audience-data-and-segmentation/user-data-tags/update-tags-via-csv/)。开发人员首次发送某个标签时，Pushwoosh 会将其创建为 User-specific 标签。如果您想自行选择标签类型，请先在控制面板中创建该标签。请参阅[使用标签管理用户数据](/zh/product/audience-data-and-segmentation/user-data-tags/tags/)。

以下标签仅为示例。请根据游戏的术语重命名它们，并添加您自己的标签：

| 标签 | 类型 | 示例 | 用途 |
| --- | --- | --- | --- |
| `player_level` | Integer | `12` | 将消息筛选到某个进度层级 |
| `is_paying_user` | Boolean | `true` | 区分面向付费玩家和未付费玩家的消息 |
| `soft_currency_balance` | Integer | `1500` | 向余额较低的玩家提供货币礼包 |
| `vip_tier` | String | `gold` | 为 VIP 玩家提供专属优惠和抢先体验 |
| `favorite_mode` | String | `pvp` | 针对玩家喜欢的模式发布限时活动公告 |

在控制面板中创建标签时，请保持 [**用户专属**](/zh/product/audience-data-and-segmentation/user-data-tags/tags/#tag-scope-general-vs-user-specific) 处于开启状态（默认即开启）。这样 Pushwoosh 会为每个 User ID 保存一个值，因此该值属于玩家，而不属于玩家的某一台设备。如果关闭 **用户专属**，每台设备都会保存自己的值。请参阅[通过 User ID 识别玩家](/zh/tutorials/industry-playbooks/mobile-games/collect-player-data/#identify-players-by-user-id)。

### 默认标签

Pushwoosh 会为每台设备存储这些[默认标签](/zh/product/audience-data-and-segmentation/user-data-tags/tags/#default-tags)，因此您无需创建它们：

* **Language**：设备的语言。Pushwoosh 用它向每位玩家发送其所用语言的消息。
* **Last Application Open**：设备上最后一次打开游戏的时间。用它来找出已停止玩游戏的玩家。
* **Push Alerts Enabled**：设备设置中是否允许通知。用它只向尚未允许通知的玩家显示 In-App 消息。
* **First Install**：设备上首次安装游戏的时间。用它来发送安装周年纪念消息。
* **Country**：设备所在的国家/地区。用它只向某一地区的玩家发送优惠或限时活动公告。