视频版讲解

Webhook 通道接入

简介/原理

神策智能运营的 Webhook 是一种 API,用以支持潜在的任何自研或第三方推送、站内信、发券系统、短信服务、... 以及任何潜在触发行为。

经过较为轻量的 REST API 对接开发,即可快速支持非神策智能运营内置的触发方式。

  • SA 作为数据输入;
    • 如上图,首先神策智能运营会读取从 SA 的实时或历史事件数据,从而进行受众计算,或实时触发;
  • 神策智能运营发送 Webhook 请求;
    • 神策智能运营会发 webhook 请求到您自身的一个 HTTP Endpoint;
  • HTTP Endpoint 拿到请求后的处理;
    • 可自行做格式转化、join 自有的其他数据、排队、buffering 等操作,并最终调用其他任何内部或外部系统(称为  Whatever System),可能调用的系统举例:
      • 第三方推送服务;
      • 站内信系统;
      • 写入 Redis;
      • 优惠券发送系统。
  • 回执事件:
    • 如果 Whatever System 是推送服务,那么可以在 App 中埋点,使 SA 得到推送回执事件。

Webhook 通道及参数配置

用户属性 vs 模板参数

#参数类型定义配置处值配置处值获取方法补充说明
1用户属性项目设置-触达方式管理-Webhook无需配置自动从用户属性中获取在通道中配置一次即可
2模板参数项目设置-触达方式管理-Webhook运营计划-计划 X-触达方式从计划配置中获取在通道中配置后,还需要在计划中填写其 ”取值“ 部分

项目设置-触达方式管理 - Webhook

如下图,通道可配置 HTTP URL、动态参数、模板参数.

运营计划-计划 X-触达方式

HTTP Endpoint Server

为与神策智能运营的 Webhook 对接,您需要开发一个 HTTP Server。其应遵循的 API 定义见下文。

Webhook Request(默认小批量合并模式)

注意,Request Body 是批量打包的:

  • Webhook 请求的 Request Body 部分是一个打包的 JSON LIST;
  • 这是为方便批量处理,神策智能运营已经对用户触发做了小批量合并;
  • 神策智能运营的 Webhook 在一个请求中包含了多个用户的触发;

Request 结构如下:

POST /your/path HTTP/1.1
Content-Type: application/json;charset=UTF-8 
Content-Length: 2737
Host: 10.42.34.43:8999
Connection: Keep-Alive
User-Agent: Apache-HttpAsyncClient/4.1.3 (Java/1.8.0_212)


[{"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }}, {"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }}, {"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }}]
CODE

Request Body 是一个 LIST:

[
   {"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }},
   {"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }},
   {"project_name": "default", "sf_version": "0.3", "user_profile": { ... }, "receipt_properties": { ... }, "params": { ... }}
]
CODE

Request Body 的 JSON LIST 解析后,每个元素是一个单用户触发的 JSON 结构(JSON 中字段名采用下划线命名,接收请求接口参数若使用驼峰命名需要注意参数反序列化字段映射):

{
    "project_name": "default",           # 神策的项目名(非显示名,而是作为标识符的英文名)
    "sf_version": "1.2",                 # 神策智能运营版本信息
    "user_profile": {                    # 神策 user profile 信息的仅 ID 部分,没有带上属性信息.
        "user_id": -5159414601538973264, # 长整数,在神策分析中用户的唯一标识
        "first_id": "EA7583CDA6678BC",   # 通常是用户的设备 ID
        "second_id": "12345678901"       # 通常是用户的登录 ID
    },
    "receipt_properties": {              # 回执属性打包,您通常不需要关心此结构的内部细节,在发送回执消息时,直接当做属性 map 使用即可.
        "sf_msg_id": "ffa71d08-f352-43eb-a1f5-5197299d2075",
        "sf_plan_id": 10,
        "sf_plan_strategy_id": 0,
		"sf_strategy_unit_id": null,
        "sf_plan_type": "运营计划",
                                         # 新增回执信息相关字段,若在创建通道时选择开启回执,则在向 WEBHOOK 服务发送请求时加上以下参数
        "sf_channel_id": 10,            
        "sf_channel_category": "WEBHOOK",    
        "sf_enter_plan_time": 1625037472000
		"sf_send_time": 1625037472000
        "cname": "会员发券"			     # 计划、画布名称;页面配置,可选下发。
		"type": "SIMPLE"				 # 计划类型,SIMPLE、RICH、CANVA;页面配置,可选下发。
		“scheduleType”: "FIXED_TIME"     # 计划调度类型,FIXED_TIME、ROUTINE、TRIGGER等;页面配置,可选下发。
		"finishTime": 1625037472000      # 计划结束时间;页面配置,可选下发。
		"componentCname": "是否购买"		 # 策略器/组件名称;页面配置,可选下发。
    },
    "params": {                          # 您在 webhook 中配置的
        "viplevel": "1",                 # “动态参数” 举例,对应到下图中的,动态参数 viplevel". 需要注意的是,params 字段无论原始类型是什么,均会被神策智能运营转换为 STRING 类型
        "action": "sample_action"        # “静态参数” 举例,对应到下图中的,静态参数 action".
    },
    "send_id": "1618307389657000"        # 发送 ID 为触达用户方式的发送标识,比如手机号、推送 ID
}
CODE

Webhook Response

HTTP 200  无 Body,神策智能运营认为全部发送成功。

HTTP 200 有 Body,并返回详细的报错信息,您需要产生一个 Response Body 以返回全部成功、失败信息,具体如下:

[
    {
        "succeed": true
    },
    {
        "succeed": false
        "fail_reason": "....."
    },
    ...
]
CODE

非 HTTP 200 状态,认为全部失败。

模板参数类型举例

注:对于任何类型的数据(如上图整数,小数,日期等类型),在发送请求时,所有字段全部转为字符串进行处理。

如上图:最终的 request 为

{
    "project_name": "default",           # 神策的项目名(非显示名,而是作为标识符的英文名)
    "sf_version": "1.2",                 # 神策智能运营版本信息
    "user_profile": {                    # 神策 user profile 信息的仅 ID 部分,没有带上属性信息.
        "user_id": -5159414601538973264, # 长整数,在神策分析中用户的唯一标识
        "first_id": "EA7583CDA6678BC",   # 通常是用户的设备 ID
        "second_id": "12345678901"       # 通常是用户的登录 ID
    },
    "receipt_properties": {              # 回执属性打包,您通常不需要关心此结构的内部细节,在发送回执消息时,直接当做属性 map 使用即可.
        "sf_msg_id": "ffa71d08-f352-43eb-a1f5-5197299d2075",
        "sf_plan_id": 10,
        "sf_plan_strategy_id": 0,
		"sf_strategy_unit_id": null,
        "sf_plan_type": "运营计划",
                                         # 新增回执信息相关字段,若在创建通道时选择开启回执,则在向 WEBHOOK 服务发送请求时加上以下参数
        "sf_channel_id": 10,            
        "sf_channel_category": "WEBHOOK",    
        "sf_enter_plan_time": 1625037472000
		"sf_send_time": 1625037472000
    },
    "params": {                          # 您在 webhook 中配置的
        "string": "string",              
        "text": "用户城市是北京",
        "datetime": "2019-08-08",
        "integer": "123",
        "decimal": "158.123",
        "percentage": "18.5"   # 注意:百分数只传对应数值,没有 %
    },
    "send_id": "1618307389657000"        # 发送 ID 为触达用户方式的发送标识,比如手机号、推送 ID
}
CODE

请求性能与延迟

高吞吐场景

如果您常见的使用模式为 ”定时”、“多次例行” 的批量计划,且每次的触发用户量很大,请联系我们提供方案。

高实时场景

为提高吞吐,对用户触发做了小批量的合并,这会导致数秒延迟。

Webhook 本身对时效性不做保证,若需要秒级或毫秒级时效性,请考虑使用智能运营 1.6 版本的弹窗,或联系神策获得技术方案。

回执事件

您可以发送一个回执的事件给 SA,并带上回执属性。

回执事件的目的是为了支持对神策智能运营更灵活的数据分析,但并非神策智能运营必备事件。

事件/属性定义如下:

namecname附带属性解释
$PlanMsgArrivedWebhook 发送成功或失败回执receipt_properties 中的属性和新增加的属性可以通过上报此事件给 SA,判断 Webhook 发送是否成功。

Webhook 发送成功或失败回执详细描述

事件预置属性

属性名称属性含义属性值

$sf_msg_status

发送状态

RECEIPT_SEND_FAILED 「发送失败」,RECEIPT_SEND_SUCCESS 「发送成功」

$sf_enter_plan_time计划进入时间长整型
$sf_send_time计划发送时间长整型
$sf_channel_id通道 ID字符串类型
$sf_channel_category通道类型WEBHOOK
$sf_plan_type计划类型运营计划,流程画布
$sf_strategy_unit_id策略器名称字符串类型
$sf_plan_strategy_id实验组 ID字符串类型
$sf_plan_id计划 ID字符串类型

备注:是否发送成功指标是指客户发送信息给具体用户,用户接收信息是否成功。

事件上报demo

webhook回执事件上报javademo

	SensorsAnalytics sa = new SensorsAnalytics(new SensorsAnalytics.ConcurrentLoggingConsumer("./access.log1"));
    Map<String, Object> properties = new HashMap<>();
    // 计划 ID
    properties.put("$sf_plan_id", "10");
    // 实验组 ID
    properties.put("$sf_plan_strategy_id", "0");
    // 策略器名称
    properties.put("$sf_strategy_unit_id", "10_10");
    // 计划类型 
    properties.put("$sf_plan_type", "运营计划");
    // 通道 ID
    properties.put("$sf_channel_id", "10");
    // 通道类型
    properties.put("$sf_channel_category", "WEBHOOK");
    // 计划进入时间
    properties.put("$sf_enter_plan_time", 1625037472000);
	// 计划发送时间
    properties.put("$sf_send_time", 1625037472000);
    
    // 发送成功指标
    properties.put("$sf_msg_status", "RECEIPT_SEND_SUCCESS");
    // 发送失败指标
    properties.put("$sf_msg_status", "RECEIPT_SEND_FAILED");
    
    // 若 second_id 有值,则优先传 second_id;若 second_id 无值,则传 first_id
	sa.track(distinctId, false, "$PlanMsgArrived", properties);
JAVA

验证数据来自神策智能运营

一些场景下,您需要验证 Webhook 请求是来自神策智能运营而不是第三方伪造的,这时您可为 Webhook 配置一个 Secret Token(目前可以提供给我们配置),该 Secret Token 在神策智能运营服务端和您的服务器上共享。

1. 神策智能运营发送请求前,对于请求的内容 REQUEST_BODY,计算 HmacSHA1(SECRET_TOKEN, REQUEST_BODY) 作为 Signature,如 cc711d5c504b757117f8823527522d512f79ffe4。
2. 发送 Webhook 请求时将添加 HTTP header X-Sf-Signature,如 X-Sf-Signature: cc711d5c504b757117f8823527522d512f79ffe4。
3. 您的服务器接到请求后,同样计算 HmacSHA1(SECRET_TOKEN, REQUEST_BODY),如果值与 header X-Sf-Signature 相同,那么可以确定是由神策智能运营服务器发送的。

其中签名函数 HmacSHA1(SECRET_TOKEN = "abc", REQUEST_BODY = "123") = be9106a650ede01f4a31fde2381d06f5fb73e612
shell 命令:echo -n '123' | openssl dgst -sha1 -hmac 'abc' 输出 be9106a650ede01f4a31fde2381d06f5fb73e612

HmacSHA1 计算代码示例:

maven 依赖:

            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.10</version>
            </dependency>
CODE

HmacSHA1 计算代码:

import org.apache.commons.codec.digest.HmacUtils;
...
String signature = HmacUtils.hmacSha1Hex(secretToken, requestBody)
CODE

Webhook 通道接入讲解视频