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

# Snowflake

> 从 Snowflake 同步自定义事件到 OneSignal，以根据用户行为触发自动化 Journey 和个性化消息推送活动。

export const PLATFORM_0 = "Snowflake"

export const DATA_TYPE_0 = "event data"

export const COLUMN_HEADER_0 = "Snowflake Column"

export const PROPERTIES_DESCRIPTION_0 = "Event metadata as VARIANT/JSON"

<Note>
  如果您正在使用 OneSignal 的旧版 Snowflake 集成，请参阅 [Snowflake 旧版集成](./snowflake-legacy)指南。
</Note>

<Frame caption="OneSignal Snowflake 集成概述">
  <img src="https://mintcdn.com/onesignal/YOTSrtBSoqdrJ37A/images/docs/4bd3285-onesignal-snowflake-integration-2.png?fit=max&auto=format&n=YOTSrtBSoqdrJ37A&q=85&s=c41bc1d77c30e6c282bb0bfdbcd67767" width="1280" height="720" data-path="images/docs/4bd3285-onesignal-snowflake-integration-2.png" />
</Frame>

***

## 概述

OneSignal + Snowflake 集成支持两种强大的数据管道：

* **导出**：自动将 OneSignal 的消息事件数据（推送、电子邮件、短信、应用内消息）发送到 Snowflake 进行分析和报告。
* **导入**：将 Snowflake 数据集中的自定义用户事件同步到 OneSignal，以触发自动化 Journey 和个性化消息。

这些集成使您可以完全控制用户参与度数据——支持高级分析和实时行为驱动的消息推送。

***

## 将 OneSignal 事件导出到 Snowflake

将消息性能和参与度事件（例如发送、打开、点击）发送到 Snowflake，以便：

* 构建自定义仪表板和报告
* 跟踪跨渠道的投递和参与度趋势
* 将 OneSignal 数据与其他业务数据结合进行分析

**要求**

* OneSignal **专业版计划**（免费应用不可用）
* [Snowflake 账户](https://docs.snowflake.com/en/user-guide/getting-started-tutorial)
* Snowflake 中的 SECURITYADMIN 或 ACCOUNTADMIN 角色（用于设置）

**设置步骤**

### 1. 收集 Snowflake 账户详细信息

在配置集成之前，请从 Snowflake 账户收集以下信息：

* **Snowflake 主机**：格式为 `<account_identifier>.snowflakecomputing.com` 的账户 URL
* **数据库名称**：OneSignal 将写入事件数据的数据库
* **架构名称**：数据库中 OneSignal 表的架构（将由 OneSignal 自动创建）
* **数据仓库名称**：用于数据加载操作的数据仓库

<Frame caption="Snowflake 账户标识符位置">
  <img src="https://mintcdn.com/onesignal/4HyuQPBpu-4xjmQC/images/docs/cf472c3-Screen_Shot_2023-06-27_at_4.08.19_PM.png?fit=max&auto=format&n=4HyuQPBpu-4xjmQC&q=85&s=ad89f70c336cfa9fc66849021cdab551" width="1554" height="620" data-path="images/docs/cf472c3-Screen_Shot_2023-06-27_at_4.08.19_PM.png" />
</Frame>

### 2. 在 Snowflake 中运行设置脚本

在 Snowflake 数据仓库中执行以下 SQL 脚本，为 OneSignal 创建必要的角色、用户、数据仓库和数据库：

```sql theme={null}
begin;

   -- create variables for user / role / warehouse / database (needs to be uppercase for objects)
   set role_name = 'ONESIGNAL_ROLE';
   set user_name = 'ONESIGNAL_USER';
   set warehouse_name = 'ONESIGNAL_WAREHOUSE';
   set database_name = 'ONESIGNAL';

   -- change role to securityadmin for user / role steps
   use role securityadmin;

   -- create role for onesignal
   create role if not exists identifier($role_name);
   grant role identifier($role_name) to role SYSADMIN;

   -- create a user for onesignal
   create user if not exists identifier($user_name)
   default_role = $role_name
   default_warehouse = $warehouse_name;

   grant role identifier($role_name) to user identifier($user_name);

   -- set binary_input_format to BASE64
   ALTER USER identifier($user_name) SET BINARY_INPUT_FORMAT = 'BASE64';

   -- set timestamp_input_format to AUTO for the user
   ALTER USER identifier($user_name) SET TIMESTAMP_INPUT_FORMAT = 'AUTO';

   -- change role to sysadmin for warehouse / database steps
   use role sysadmin;

   -- create a warehouse for onesignal
   create warehouse if not exists identifier($warehouse_name)
   warehouse_size = xsmall
   warehouse_type = standard
   auto_suspend = 60
   auto_resume = true
   initially_suspended = true;

   -- create database for onesignal
   create database if not exists identifier($database_name);

   -- grant onesignal role access to warehouse
   grant USAGE
   on warehouse identifier($warehouse_name)
   to role identifier($role_name);

   -- grant onesignal access to database
   grant CREATE SCHEMA, MONITOR, USAGE
   on database identifier($database_name)
   to role identifier($role_name);

 commit;
```

<Note>
  您可以自定义脚本顶部的变量值以匹配您的命名约定。如果您使用现有的数据仓库或数据库，请相应地修改脚本。
</Note>

### 3. 生成密钥对进行身份验证

OneSignal 需要密钥对身份验证才能安全访问您的 Snowflake 账户。按照以下步骤生成和配置密钥：

<Steps>
  <Step title="生成私钥">
    运行以下命令之一以生成私钥：

    **未加密的私钥**（更简单，但安全性较低）：

    ```bash theme={null}
    openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
    ```

    **加密的私钥**（推荐用于生产环境）：

    ```bash theme={null}
    openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 aes256 -inform PEM -out rsa_key.p8
    ```

    如果使用加密密钥，系统将提示您创建密码短语。请妥善保存此密码短语——在配置 OneSignal 时您将需要它。
  </Step>

  <Step title="生成公钥">
    从私钥生成公钥：

    ```bash theme={null}
    openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
    ```
  </Step>

  <Step title="将公钥分配给 Snowflake 用户">
    复制公钥文件的内容（不包括页眉和页脚行），然后在 Snowflake 中运行此 SQL 命令：

    ```sql theme={null}
    ALTER USER ONESIGNAL_USER SET RSA_PUBLIC_KEY='<YOUR_PUBLIC_KEY_CONTENT>';
    ```

    将 `<YOUR_PUBLIC_KEY_CONTENT>` 替换为密钥内容（不包括 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 行）。
  </Step>
</Steps>

<Warning>
  妥善存储您的私钥文件。您需要在下一步中将其提供给 OneSignal。切勿公开分享您的私钥或将其提交到版本控制系统。
</Warning>

### 4. 连接 OneSignal

<Steps>
  <Step title="激活集成">
    在 OneSignal 中，导航至**数据 > 集成 > Snowflake**。
  </Step>

  <Step title="输入详细信息">
    * 主机：`<your_account>.snowflakecomputing.com`
    * 数据库：例如 `ONESIGNAL`
    * 架构
    * 表：例如 `message_events`
    * 用户：`ONESIGNAL_USER`（或您创建的用户名）
    * 私钥：粘贴私钥文件的内容（`rsa_key.p8`）
    * 私钥密码短语（可选，仅当私钥已加密时）
  </Step>

  <Step title="配置集成">
    * **同步频率：** 最频繁可为每 15 分钟一次
    * **架构/表名称：** 预设为 `onesignal_events_<app-id>` 和 `message_events`（可编辑）
    * **事件类型：** 选择要同步的事件——全选或仅选择您需要的
  </Step>

  <Step title="选择事件">
    选择您想在 Snowflake 数据仓库中接收的事件。
  </Step>

  <Step title="完成设置">
    点击**保存**并等待成功确认
  </Step>
</Steps>

<Note>
  初始数据同步可能需要 15-30 分钟才能在 Snowflake 中显示。

  在等待期间，通过推送、电子邮件、应用内消息或短信发送消息以触发所选事件。
</Note>

### 5. 在 Snowflake 中查看数据

初始同步完成后，查询您的 OneSignal 事件数据：

```sql theme={null}
-- View recent message events
SELECT *
FROM <your-database>.<your-schema>.message_events
ORDER BY _CREATED DESC
LIMIT 100;
```

<Info>
  如果您遇到缺少架构、权限错误或格式错误的事件等问题，请联系 `support@onesignal.com`。
</Info>

## 消息事件和属性

### 消息事件类型

**属性：** `event_kind`
**类型：** `String`

消息和事件的类型（例如 `message.push.received`、`message.push.sent`）。

| 消息事件 (OneSignal) |           `event_kind`           | 描述              |
| :--------------: | :------------------------------: | --------------- |
|       推送已发送      |        `message.push.sent`       | 推送通知成功发送。       |
|       推送已接收      |      `message.push.received`     | 推送确认已送达并被用户接收。  |
|       推送已点击      |      `message.push.clicked`      | 用户点击了推送。        |
|       推送失败       |       `message.push.failed`      | 送达失败。查看消息报告。    |
|      推送已取消订阅     |    `message.push.unsubscribed`   | 用户取消订阅推送。       |
|       应用内展示      |     `message.iam.impression`     | 应用内消息已显示。       |
|       应用内点击      |       `message.iam.clicked`      | 应用内消息已点击。       |
|      应用内页面查看     |   `message.iam.page_displayed`   | 应用内页面已显示。       |
|       邮件已发送      |       `message.email.sent`       | 邮件已送达。          |
|       邮件已接收      |     `message.email.received`     | 邮件已被接收方邮件服务器接受。 |
|       邮件已打开      |      `message.email.opened`      | 用户已打开邮件。        |
|      邮件链接已点击     |      `message.email.clicked`     | 邮件中的链接已点击。      |
|      邮件已取消订阅     |   `message.email.unsubscribed`   | 接收方已取消订阅。       |
|    邮件已标记为垃圾邮件    | `message.email.reported_as_spam` | 用户将您的邮件标记为垃圾邮件。 |
|       邮件已退回      |      `message.email.bounced`     | 由于永久性送达失败而退回。   |
|       邮件失败       |      `message.email.failed`      | 送达失败。           |
|       邮件已抑制      |    `message.email.suppressed`    | 由于抑制列表而被抑制。     |
|       短信已发送      |        `message.sms.sent`        | 短信已发送。          |
|       短信已送达      |      `message.sms.delivered`     | 短信成功送达。         |
|       短信失败       |       `message.sms.failed`       | 短信送达失败。         |
|       短信未送达      |     `message.sms.undelivered`    | 短信被拒绝或无法到达。     |

### 事件数据架构

对于用户生成的每个消息事件，以下元数据将附加到记录中。

|                       列名称                       |     类型    | 描述                                 |
| :---------------------------------------------: | :-------: | ---------------------------------- |
|                    `event_id`                   |    UUID   | 事件的唯一标识符                           |
|                `event_timestamp`                | Timestamp | 事件发生时间                             |
|                   `event_kind`                  |   String  | [事件类型](#message-event-kinds)       |
|            `subscription_device_type`           |   String  | 设备类型（例如，iOS、Android、Web、Email、SMS） |
|                    `language`                   |   String  | 订阅语言代码                             |
|                    `version`                    |   String  | 集成版本                               |
|                   `device_os`                   |   String  | 设备操作系统版本                           |
|                  `device_type`                  |   Number  | 数字设备类型                             |
|                     `token`                     |   String  | 推送令牌、电话号码或邮箱                       |
|                `subscription_id`                |    UUID   | 订阅 ID                              |
|                   `subscribed`                  |  Boolean  | 订阅状态                               |
|                  `onesignal_id`                 |    UUID   | OneSignal 用户 ID                    |
|                  `last_active`                  |   String  | 上次活跃时间戳                            |
|                      `sdk`                      |   String  | OneSignal SDK 版本                   |
|                  `external_id`                  |   String  | 应与集成用户 ID 匹配的外部用户 ID               |
|                     `app_id`                    |    UUID   | 来自 OneSignal 的应用 ID                |
|                  `template_id`                  |    UUID   | 模板 ID（如适用）                         |
|                   `message_id`                  |    UUID   | 消息批处理/请求 ID                        |
|                  `message_name`                 |   String  | 消息名称                               |
|                 `message_title`                 |   String  | 消息标题（仅英语）                          |
|                `message_contents`               |   String  | 截断的消息正文（仅英语）                       |
|                 `failure_reason`                |   String  | 失败原因（适用于推送失败和邮件失败事件）               |
| `_created`, `_id`, `_index`, `_fivetran_synced` |   *内部使用*  | Fivetran 同步元数据                     |

### 注意事项

* 保存/激活后的同步可能需要额外 15-30 分钟才能完成。
* 停用后可能仍会进行最后一次同步。
* 为确保高效的数据同步，我们的系统会自动创建和管理暂存数据集。这些数据集以 `fivetran_{两个随机单词}_staging` 的模式命名，在处理过程中临时存储数据，然后再集成到您的主架构中。这些暂存数据集对于维护流畅的工作流程至关重要，不应删除，因为它们会被自动重新创建。

***

## 从 Snowflake 导入事件

将行为事件数据从 Snowflake 发送到 OneSignal，以便：

* 根据用户活动触发 Journey
* 根据行为数据个性化消息

**要求**

* 访问自定义事件（目前处于测试阶段）
* [升级账户计划](https://onesignal.com/pricing)（免费应用不可用）。

- 具有数据仓库访问权限的 **Snowflake 账户**
- 存储在 Snowflake 表或视图中的**事件数据**
- 从 OneSignal 到您的 Snowflake 实例的**网络连接**
- 具有适当权限的**用户凭证**

**设置步骤**

<Steps>
  <Step title="为 OneSignal 创建专用角色">
    按照 Snowflake 最佳实践创建角色层次结构：

    ```sql theme={null}
    -- Create a role for the census user
    CREATE ROLE CENSUS_ROLE;

    -- Ensure the sysadmin role inherits any privileges the census role is granted
    GRANT ROLE CENSUS_ROLE TO ROLE SYSADMIN;
    ```
  </Step>

  <Step title="创建专用数据仓库">
    为 OneSignal 操作创建经济高效的数据仓库：

    ```sql theme={null}
    -- Create a warehouse for the census role, optimizing for cost over performance
    CREATE WAREHOUSE CENSUS_WAREHOUSE WITH
        WAREHOUSE_SIZE = XSMALL
        AUTO_SUSPEND = 60
        AUTO_RESUME = TRUE
        INITIALLY_SUSPENDED = FALSE;

    GRANT USAGE ON WAREHOUSE CENSUS_WAREHOUSE TO ROLE CENSUS_ROLE;
    GRANT OPERATE ON WAREHOUSE CENSUS_WAREHOUSE TO ROLE CENSUS_ROLE;
    GRANT MONITOR ON WAREHOUSE CENSUS_WAREHOUSE TO ROLE CENSUS_ROLE;
    ```
  </Step>

  <Step title="创建用户并授予权限">
    创建 OneSignal 用户并授予对事件数据的访问权限：

    ```sql theme={null}
    -- Create the census user
    CREATE USER CENSUS WITH
        DEFAULT_ROLE = CENSUS_ROLE
        DEFAULT_WAREHOUSE = CENSUS_WAREHOUSE
        PASSWORD = '<strong-unique-password>';

    GRANT ROLE CENSUS_ROLE TO USER CENSUS;

    -- Grant access to your event data (replace with your actual database/schema)
    GRANT USAGE ON DATABASE "<your-database>" TO ROLE CENSUS_ROLE;
    GRANT USAGE ON SCHEMA "<your-database>"."<your-schema>" TO ROLE CENSUS_ROLE;
    GRANT SELECT ON ALL TABLES IN SCHEMA "<your-database>"."<your-schema>" TO ROLE CENSUS_ROLE;
    GRANT SELECT ON FUTURE TABLES IN SCHEMA "<your-database>"."<your-schema>" TO ROLE CENSUS_ROLE;
    GRANT SELECT ON ALL VIEWS IN SCHEMA "<your-database>"."<your-schema>" TO ROLE CENSUS_ROLE;
    GRANT SELECT ON FUTURE VIEWS IN SCHEMA "<your-database>"."<your-schema>" TO ROLE CENSUS_ROLE;
    ```
  </Step>

  <Step title="创建记账数据库（高级同步引擎）">
    为 OneSignal 的同步状态管理创建私有数据库：

    ```sql theme={null}
    -- Create a private bookkeeping database
    CREATE DATABASE "CENSUS";
    GRANT ALL PRIVILEGES ON DATABASE "CENSUS" TO ROLE CENSUS_ROLE;

    CREATE SCHEMA "CENSUS"."CENSUS";
    GRANT ALL PRIVILEGES ON SCHEMA "CENSUS"."CENSUS" TO ROLE CENSUS_ROLE;
    GRANT CREATE STAGE ON SCHEMA "CENSUS"."CENSUS" TO ROLE CENSUS_ROLE;
    ```

    <Warning>
      如果使用基本同步引擎或只读模式，请跳过此步骤。
    </Warning>
  </Step>

  <Step title="配置身份验证">
    设置密钥对身份验证（推荐）以增强安全性：

    1. 按照 [Snowflake 文档](https://docs.snowflake.com/en/user-guide/key-pair-auth)生成公钥/私钥对
    2. 在 Snowflake 用户上配置公钥
    3. 在 OneSignal 的连接设置中使用私钥

    或者，您可以使用密码身份验证（已弃用 - 将于 2025 年 11 月被阻止）。
  </Step>

  <Step title="连接到 OneSignal">
    在 OneSignal 中，前往 **数据 > 集成**，然后点击 **添加集成**。

    选择 **Snowflake** 并提供以下连接详细信息：

    * **账户名称：** 您的 Snowflake 账户标识符（例如 `abc123.us-east-1`）
    * **数据仓库：** `CENSUS_WAREHOUSE`
    * **用户：** `CENSUS`
    * **数据库：** 您的事件数据数据库名称
    * **架构：** 您的事件数据架构名称
    * **身份验证：** 密钥对（提供私钥和可选密码短语）
  </Step>
</Steps>

***

### 事件数据映射

将您的 {PLATFORM_0} {DATA_TYPE_0} 映射到 OneSignal 的自定义事件格式：

| OneSignal 字段  | {COLUMN_HEADER_0} | 描述                         | 必需 |
| ------------- | ----------------- | -------------------------- | -- |
| `name`        | `event_name`      | 事件标识符                      | 是  |
| `external_id` | `user_id`         | 用户标识符                      | 是  |
| `timestamp`   | `event_timestamp` | 事件发生时间                     | 否  |
| `properties`  | `event_data`      | {PROPERTIES_DESCRIPTION_0} | 否  |

#### 示例事件表架构

```sql theme={null}
-- Example Snowflake event table
CREATE TABLE analytics.user_events (
    event_id STRING,
    event_name STRING NOT NULL,
    user_id STRING NOT NULL,
    event_timestamp TIMESTAMP_TZ DEFAULT CURRENT_TIMESTAMP(),
    event_properties VARIANT,
    session_id STRING,
    device_type STRING
);
```

#### SQL 查询模式

编写自定义 SQL 查询以转换您的事件数据：

```sql theme={null}
-- Example: Recent high-value events
SELECT
    event_name,
    user_id,
    event_timestamp,
    event_properties
FROM analytics.user_events
WHERE event_timestamp >= DATEADD(day, -7, CURRENT_TIMESTAMP())
    AND event_properties:value::NUMBER > 100
ORDER BY event_timestamp DESC;
```

### 高级配置

#### 管理数据仓库成本

* 使用 X-Small 数据仓库大小以优化成本
* 配置自动挂起（60 秒）和自动恢复
* 在非高峰时段安排同步
* 考虑与其他批处理系统共享数据仓库

#### 实时同步支持

要进行实时事件处理，请在事件表上启用变更跟踪：

```sql theme={null}
ALTER TABLE "analytics"."user_events" SET CHANGE_TRACKING = TRUE;
```

#### 网络安全

如果使用 Snowflake 的允许 IP 网络策略，请将 OneSignal 的 IP 地址添加到您的允许列表。请联系 OneSignal 支持以获取当前的 IP 范围。

***

## 限制

* 复杂的分析查询可能会影响数据仓库性能和成本
* 用户/密码身份验证将于 2025 年 11 月弃用
* CENSUS 数据库仅保留用于 OneSignal 操作

***

## 常见问题

### 我应该使用哪种身份验证方法？

使用**密钥对身份验证**（推荐）。从 2025 年 11 月开始，Snowflake 将阻止用户/密码身份验证。

### 我可以使用现有的数据仓库吗？

可以，您可以与其他批处理系统（如 dbt 或 Fivetran）共享数据仓库以优化成本。确保数据仓库具有足够的容量来满足您的事件处理需求。

### 如何优化成本？

* 使用 X-Small 数据仓库大小
* 配置激进的自动挂起（60 秒）
* 在非高峰时段安排同步
* 使用每小时/每天同步而不是连续同步

***
