服务器到服务器集成指南
服务器到服务器用例
Singular SDK 必须嵌入到应用程序中,作为Singular SDK 的替代方案,Singular 还提供了一个 REST API,可用于构建一个完整的集成,无需使用 Singular SDK 即可在自己的服务器上运行。本指南将解释构建完整的服务器到服务器集成背后的概念,并重点介绍所有高级功能。
混合使用案例
作为100%服务器到服务器集成的替代方案,你可以使用Singular SDK来处理会话管理以及所有高级功能和数据收集要求,从而实现混合使用。此外,还可利用服务器到服务器 EVENT API 从后端服务器发送事件。
混合使用案例详情
从服务器发送应用程序外移动事件或网站事件数据到Singular时,必须包含Singular移动SDK或Web SDK中的相应标识符。这样可以确保事件活动准确归属于正确的设备。
数据流
有两种主要方法可以检索设备数据:
- 客户端管理数据流:这种方法是在客户端捕获所有所需的数据点,并通过自己的 API 将其传递到服务器。这种方法允许你直接从客户端(如移动应用程序或网站)收集设备标识符、事件数据和其他必要的属性,并将它们转发到你的服务器,在那里你可以使用服务器到服务器的 EVENT API 进行处理并将它们发送到 Singular。
- 回传:该选项用于配置Singular 内部 BI回传,允许 Singular 向指定端点发送带有 JSON 有效载荷的回传。安装、重新吸引和/或应用内事件发生后,该回传将实时发送。有效载荷将包括成功发送应用程序外服务器端事件所需的所有必要数据点。有关设置内部 BI 回传的详细说明,请单击[此处]。
这两个选项都可能需要一些服务器端逻辑来维护设备图。如果 Singular SDK 检测到设备标识符发生变化,服务器必须进行相应更新,以确保准确跟踪和归因。
要实施第一种方案,即从应用程序中捕获设备标识符和参数,并将其发送到服务器供 Singular API 端点使用,请查看以下文章以获得指导:
- 查看事件端点所需参数。
- 查看《服务器到服务器检索设备数据指南》中的 iOS 和 Android 代码示例,以帮助检索特定设备标识符和设备数据点。
查看下面的一般指南,以遵循服务器到服务器配置的一般指南。在混合使用情况下,您可以省略 SESSION 端点,因为 Singular SDK 将为您管理该端点。
要点
- 灵活性:完全控制数据收集和传输。
- 功能对等:在提供适当数据的情况下,支持所有 SDK 功能。
- 集成路径:客户端 → 服务器 → Singular API
- 实时处理:一次一个请求,无批量处理。
- 顺序数据流:事件必须按时间顺序处理。
- 重复数据删除: Singular不会重复接收数据。建议发送一个(1)成功的请求并保存日志,以备重放请求。
- 数据验证: 设备级数据是永久性的,一旦接收就无法删除。在向 Singular 发送数据之前,请执行全面的数据验证,以确保数据的准确性。
要求
SDK 会自动收集设备和应用程序数据,而 S2S 方法则要求您
- 从应用程序中收集所需的数据点。
- 将这些数据转发到服务器并存储在设备图中。
- 通过SESSION API 端点向 Singular 发送会话请求。
- 将 Singular 的响应传回应用程序。
- 通过EVENT API 端点将事件请求转发给 Singular。
REST API 端点
会话端点
GET https://s2s.singular.net/api/v1/launch
会话端点 API 参考
事件端点
GET https://s2s.singular.net/api/v1/evt
事件端点 API 参考
开始使用
要成功集成用于跟踪应用程序会话和事件的 Singular REST API,您需要实施一个全面的数据管道,其中包括四个关键阶段。
- 在应用程序中建立强大的数据收集策略,捕获并存储相关的用户交互以及服务器端数据库中的 Singular 所需的数据点。
- 创建实时数据流机制,将捕获的事件从服务器即时转发到 Singular 的 REST API 端点。
- 实施适当的响应处理,以处理 Singular 的 API 响应,确保数据传输成功并进行适当的错误管理。
- 对所有数据流进行全面测试,以验证集成的准确性和可靠性。
这种系统化的方法可确保无缝数据传输,同时保持数据的完整性以及应用程序与 Singular 分析平台之间的实时同步。
数据收集
Singular要求每个端点都有特定的数据点,这是提供Singular平台功能所必需的。所有必要的参数都是必需的,如果遗漏会导致数据或功能不一致。
提示: 在收集客户端数据并将其发送回服务器以便与 Singular API 配合使用时,请务必等待异步函数返回并处理各种边缘情况。这是一个常见问题,可能导致数据丢失和部分归属。
- 查看会话端点所需参数。
- 查看事件端点所需参数。
- 查看《服务器到服务器检索设备数据指南》中的 iOS 和 Android 代码示例,以帮助检索特定设备标识符和设备数据点。
- 查看《服务器到服务器 SKAdNetwork 4 实施指南》中的 iOS 代码示例,以协助检索特定 SkAdNetwork 4 设备数据点。
- 查看并确定下面所需的高级选项部分。
捕获所需数据点并将其提供给服务器后,您就可以将会话和事件请求流传输到 Singular。
实时数据流
实时数据流对于保持准确的归因和营销活动性能测量至关重要。在实施服务器端跟踪时,数据传输的时间和顺序会直接影响 Singular 提供的分析和优化功能的质量。
关键的时间考虑因素
- 归因准确性:会话报告延迟会严重影响归因的准确性,因为系统需要精确的时间数据才能正确地将用户行为与营销活动联系起来。
- SKAdNetwork 的影响:iOS SKAdNetwork 转换值的时间敏感性使得实时数据流变得尤为重要。由于转换值更新有严格的设备上计时器窗口,事件报告的任何延迟都可能导致错过更新转换值的机会,从而导致营销活动绩效数据不完整或不准确。
在构建数据流时应牢记一些最佳实践:
- 为应用程序会话启动实施服务器端事件监听器。
- 立即将会话数据转发到 Singular 的 REST API,并提供所有需要的数据点。
- 为应用内事件实施服务器端事件监听器。
- 立即将事件数据转发给 Singular 的 REST API,并提供所有必要的数据点。
- 使用 webhook 架构实现可靠的数据传输。
- 针对失败请求实施重试机制。
- 监控数据流以保证质量。
配置好实时流后,继续处理响应。
响应处理
响应处理是连接服务器端 API 交互与客户端功能的另一个关键组件。这种双向通信可确保 Singular API 有价值的响应数据到达移动应用程序,从而实现延迟深度链接和转换值更新等关键功能。
关键响应类型
- 延迟深度链接:当新会话启动时,API 响应可能包含待处理的深度链接数据,需要立即转发给应用程序,以实现正确的用户路由和个性化体验。
- 转换值:对于 iOS 营销活动,转换端点提供更新的 SKAdNetwork 转换值,必须及时转发到应用程序,以保持准确的营销活动测量。
在构建响应处理流程时应牢记一些最佳实践:
- 在客户端服务器上实施响应处理。
- 解析并验证 Singular API 响应。
- 将相关响应数据转发给客户端应用程序。对 iOS SKAdNetwork 转换值更新至关重要。
- 实施客户端响应处理。
- 使用适当的状态代码优雅地处理错误。
- 记录重试机制的失败响应。
响应处理已完成,现在是测试数据管道并验证所有数据流是否按预期运行并提供正确数据的时候了。
测试数据流
测试阶段对成功部署至关重要。与 Singular 最基本的集成包括在用户会话发生时通知 Singular,允许 Singular 触发多个内部流程:
- 如果这是应用程序在特定设备上的首次会话,Singular 会识别为新安装并触发安装归因流程。
- 如果会话符合重新参与会话的条件,Singular 会触发重新参与归因流程(在重新参与常见问题中了解更多信息)。
- 否则,Singular 会将其标记为会话,用于跟踪用户活动和保留指标。
向 Singular 服务器发出会话请求和后续事件请求的时机至关重要:
-
在发生任何事件之前,必须先收到一个会话。
例如,当用户开始使用应用程序时,Singular SDK 会在应用程序打开时触发会话,然后在会话后发送应用程序内事件。如果用户将应用置于后台的时间较长(超过 1 分钟),会话就会超时。当应用程序回到前台时,将发送另一个会话。建议使用应用程序生命周期事件和计时器来帮助管理会话,并调节对 Singular 的会话请求。 - 应用程序中发生的事件必须在各自会话结束后实时发送。
- 测试会话数据流,验证第一个会话和后续会话是否有各自的数据点和正确的值。
- 确认只有在会话报告给 Singular 后才会收到事件。如果事件是在会话之前收到的,那么将为设备创建一个有机属性,这可能会导致报告中出现不希望出现的结果。
- 确认会话响应已处理并传回客户端应用程序。这在支持 Singular 活动的延迟深度链接时至关重要。
成功:
- 您已验证了所需数据点的数据收集和存储!
- 验证了到 Singular 的实时数据流!
- 您已经验证了对 Singular 请求的响应处理和日志记录!
- 您已验证所有测试数据流!
高级选项
要利用 Singular 服务器到服务器(S2S)集成的高级选项,需要使用附加参数增强会话通知端点。
这一过程包括
- 确定所需的高级功能。
- 找到相应的特殊参数。
- 将这些参数纳入现有端点配置。
查看以下可用的高级选项:
附加归因处理
Apple 搜索广告系列的归因 (iOS)
Apple Search Ads 被视为自归因网络 (SAN)。 自 iOS 14.3 起,Apple Search Ads 整合通过两个 iOS 框架提供支持:
- 对于 iOS 14.2 及以下版本,Apple Search Ads 通过iAd 框架提供支持。
- 对于 iOS 14.3 及以上版本,Apple Search Ads 通过AdServices 框架提供支持。
我们建议同时使用 iAd 和 AdServices 框架,直到 iAd 框架在将来被淘汰。 由于 AdServices 仍是一项新的苹果服务,Singular 将同时使用这两项服务,但在归因和报告方面,AdServices 将优先于 iAd 信号。
更多信息,请参阅我们的苹果搜索广告集成文档。
通过 iAd 实施苹果搜索广告(iOS 14.2 及以下版本)
1.检索归因数据:
要检索归因数据,请使用Apple Search Ads iAd API。调用requestAttributionDetails(_:):返回包含属性数据的 JSON 对象。
例如
#import <iAd/iAd.h>
Class ADClientClass = NSClassFromString(@"ADClient");
if (ADClientClass) {
id sharedClient = [ADClientClass performSelector:@selector(sharedClient)];
if ([sharedClient respondsToSelector:@selector(requestAttributionDetailsWithBlock:)]) {
[sharedClient requestAttributionDetailsWithBlock:^(NSDictionary *attributionDetails, NSError *error) {
if (attributionDetails && attributionDetails.count > 0) {
// REPORT attributionDetails FROM YOUR APP TO YOUR SERVER
}
}];
}
}
- 在检索归因数据前设置几秒钟的延迟。
- 如果响应为 "False "或错误代码(0、2、3),则执行重试逻辑。2 秒后再次调用 Apple Attribution API。
2.将归因数据发送给 Singular:
要与 Singular 共享归因数据,请使用 "事件通知"(EventNotification)端点报告保留事件名称为__iAd_Attribution__ 的事件。将上一步中获取的 JSON 对象作为e 参数 的值传入,如下例所示。
import requests
import json
SDK_KEY = '[sdk_key from Developer tools > SDK Integration > SDK keys]'
EVENT_URL = 'https://s2s.singular.net/api/v1/evt'
# !!! REPLACE WITH COLLECTED VALUE FROM APP !!!
apple_attribution_data = {
u'Version3.1': {
u'iad-adgroup-id': u'1234567',
u'iad-adgroup-name': u'Ad Group Name',
u'iad-attribution': u'true',
u'iad-campaign-id': u'1234567',
u'iad-campaign-name': u'Search Campaign',
u'iad-click-date': u'2016-05-21T12:19:31Z',
u'iad-conversion-date': u'2016-05-21T12:19:41Z',
u'iad-keyword': u'ballon',
u'iad-lineitem-id': u'1234567',
u'iad-lineitem-name': u'Line Item Name',
u'iad-org-name': u'Cool Company',
u'iad-purchase-date': u'2016-05-21T12:19:41Z'
}
}
params = {
'n': '__iAd_Attribution__',
'e': json.dumps(apple_attribution_data),
'a': SDK_KEY,
'p': 'iOS',
'i': 'com.singular.app',
'ip': '10.1.2.3',
've': '9.2',
'mo': 'iPhone9%2C4',
'lc': 'en_US',
'idfa': '8ECD7512-2864-440C-93F3-A3CABE62525B',
'idfv': '38548D9F-3F73-4D4B-8545-9A920CC89191',
'utime': 1483228800
}
result = requests.get(EVENT_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/evt?n=__iAd_Attribution__&e=%7B%22Version3.1%22%3A%7B%22iad-purchase-date%22%3A%20%222016-10-25T22%3A24%3A35Z%22%2C%22iad-keyword%22%3A%20%22ballon%22%2C%22iad-adgroup-id%22%3A%20%221234567%22%2C%22iad-campaign-id%22%3A%20%221234567%22%2C%22iad-lineitem-id%22%3A%20%221234567%22%2C%22iad-org-id%22%3A%20%224070%22%2C%22iad-org-name%22%3A%20%22Cool%20Company%22%2C%22iad-campaign-name%22%3A%20%22Search%20Campaign%22%2C%22iad-conversion-date%22%3A%20%222016-05-21T12%3A19%3A41Z%22%2C%22iad-conversion-type%22%3A%20%22Redownload%22%2C%22iad-click-date%22%3A%20%222016-05-21T12%3A19%3A31Z%22%2C%22iad-attribution%22%3A%20%22true%22%2C%22iad-adgroup-name%22%3A%20%22Ad%20Group%20Name%22%2C%22iad-lineitem-name%22%3A%20%22Line%20Item%20Name%22%7D%7D&a=SDK_KEY&p=iOS&i=com.singular.app&ip=10.1.2.3&ve=9.2&ma=Apple&mo=iPhone8%2C1&lc=en_US&idfa=8ECD7512-2864-440C-93F3-A3CABE62525B&idfv=38548D9F-3F73-4D4B-8545-9A920CC89191&utime=1568948680
注意
- 对于 iOS 13+,必须在安装或重装后的第一次会话后立即发送 __iAd_Attribution__事件。否则,Apple Search Ads 数据将不会被视为归因。
- 在 iOS 14+ 中,Apple Search Ads 归因响应仅在特定条件下可用,如果 AppTrackingTransparency 状态为ATTrackingManager.AuthorizationStatus.denied,则不可用。
通过 AdServices 实施 Apple Search Ads(iOS 14.3 及以上版本)
1.读取归属标记:
在安装或重装后首次初始化应用程序时,立即使用attributionToken()提取归属令牌。
例如
#import <AdServices/AdServices.h>
NSError *error = nil;
Class AAAttributionClass = NSClassFromString(@"AAAttribution");
if (AAAttributionClass) {
NSString *attributionToken = [AAAttributionClass attributionTokenWithError:&error];
if (!error && attributionToken) {
// Handle attributionToken
}
}
备注:
- 属性令牌在设备上生成。
- 生成后,令牌会在设备上缓存 5 分钟。 5 分钟后,如果调用 attributionToken() 会生成一个新令牌。
- 生成的标记有效期为 24 小时。
2.将归属令牌发送给 Singular:
对令牌进行 URL 编码,然后通过会话通知端点将令牌发送给 Singular,并附加到&attribution_token=参数中。 该令牌应在每次安装和重新安装后的第一次会话中发送,以便 Singular 跟踪苹果搜索广告的下载和重新下载情况。
重要:发送 Google Play 安装推荐人(安卓)
安装推荐人包含关于谁将用户发送到 Google Play 商店的信息。当 Singular 可以使用安装推荐人时,它就能提供最准确的安装属性。在第一次会话通知调用时,读取此值并将其传递给 Singular。 一些重要的 Singular 功能需要它,例如在用户级导出(User-Level Exports)中接收 Facebook 数据、与数据目的地(Data Destinations)共享数据以及发送回帖。
Google Play 会在用户访问商店时收集推荐人信息。如果用户后来安装了他们被引导到的应用程序,Google Play 就会向该应用程序提供这些信息。有关详细信息,请参阅Google 的开发者文档。
与 Singular 共享安装推荐器:
- 首次打开应用程序时,使用Play Install Referrer API 获取安装参考源。
-
使用包含参数install_ref 的会话通知端点向 Singular 报告会话。该参数为 JSON 编码,具有以下属性:
属性 属性 referrer
从 Play Install Referrer API 获取的推荐值。这是一个 JSON 对象,因此请确保将其编码为字符串。 referrer_source
指定为 "服务"。 clickTimestampSeconds
从 Play Install Referrer API 接收到的点击时间戳(例如,"1550420123")。 installBeginTimestampSeconds
从 Play Install Referrer API 接收到的安装开始时间。 current_device_time
当前设备的时间,以毫秒为单位(例如,"1550420454906")。
以下是报告安装推荐人事件的示例代码:
import requests
import json
SDK_KEY = '[sdk_key from Developer tools > SDK Integration > SDK keys]'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
referrer_values = {
"referrer": "tracking_id%3D123456789&utm_source%3Dmdotm%26utm_medium%3Dbanner%26utm_campaign%3Dcampaign",
"referrer_source" : "service",
"clickTimestampSeconds" : 1550420123,
"installBeginTimestampSeconds" : 1550420123,
"current_device_time" : 1550420454906
}
referrer_values = json.dumps(referrer_values, separators=(',',':'))
params = {
'a': SDK_KEY,
'p': 'Android',
'i': 'com.singular.app',
'ip': '10.1.2.3',
've': '9.2',
'ma': 'samsung',
'mo': 'SM-G935F',
'lc': 'en_US',
'aifa': '8ecd7512-2864-440c-93f3-a3cabe62525b',
'andi': 'fc8d449516de0dfb',
'utime': 1483228800,
'dnt': 0,
'install':'true',
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'fcm':'bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1',
'app_v':'1.2.3',
'openuri':'myapp%3A%2F%2Fhome%2Fpage%3Fqueryparam1%3Dvalue1',
'ddl_enabled':'false',
'install_source': 'com.android.vending',
'install_time': 1510040127,
'update_time': 1510090877,
'custom_user_id': '123456789abcd',
'install_ref' : referrer_values
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/launch?aifa=8ecd7512-2864-440c-93f3-a3cabe62525b&andi=fc8d449516de0dfb&p=Android&a=SDK_KEY&i=com.singular.app&ip=10.1.2.3&ve=9.2&dnt=0&n=MyCoolApp&dnt=0&c=wifi&cn=Comcast&lc=en_US&bd=Build%2FMMB29K&ma=samsung&mo=SM-G935F&custom_user_id=123456789abcd&install_ref=%7B%22installBeginTimestampSeconds%22%3A%221568939453%22%2C%22referrer%22%3A%22utm_source%3Dgoogle-play%26utm_medium%3Dorganic%22%2C%22clickTimestampSeconds%22%3A%220%22%2C%22referrer_source%22%3A%22service%22%2C%22current_device_time%22%3A%221568944524%22%7D%0A
元安装推荐人归属(安卓)
"Meta Referrer "是 Facebook 推出的 Android 专用测量解决方案,允许广告商访问 Android 应用程序安装的细粒度用户级归因数据(请参阅 Facebook 的数据政策)。它由实施 "Google Play 安装推荐人"(请参阅 "传递 Google 安装推荐人")和 "元安装推荐人 "技术组成,用于测量应用程序的安装情况。请在常见问题解答中阅读有关Meta Referrer的更多信息。
与 Singnular 共享 Meta Install Referrer 信息:
- 首次打开应用程序时,根据Meta 文档检索 Meta 安装 Referrer。
-
使用会话通知端点(Session Notification endpoint)向Singular报告会话,包括参数meta_ref。该参数为 JSON 编码,具有以下属性:
属性 属性 is_ct
从 Meta 安装 Referrer 接收到的 "is_ct"。(例如 0 或 1) install_referrer
从元安装推荐器接收到的 "install_referrer actual_timestamp
从元安装推荐器接收到的 "actual_timestamp"(实际时间戳)(例如 1693978124)。
奇异链接支持
深层链接是可点击的链接,可将用户引向应用程序内的特定内容。当用户在安装了应用程序的设备上点击深层链接时,应用程序就会打开并显示特定的产品或体验。
奇异跟踪链接可包括深度链接和延迟深度链接(更多信息,请参阅我们的 深度链接常见问题和奇异链接常见问题)。
启用深度链接
深度链接的先决条件
必须对客户端应用程序进行配置,以便将奇异链接识别为 iOS 通用链接或 Android 应用程序链接。请按照 "奇异链接先决条件"指南启用 iOS 和 Android 深度链接。
实施深度链接
通过深度链接打开应用时,捕获openURL并将其添加到发送给Singular的会话通知请求中,方法是将URL值追加到openuri 参数中。使用 Singular 链接时需要这样做。
必须更新客户端应用程序代码,以解析和处理来自 Singular 链接 URL 的深度链接参数。如果奇异链接导致了成功的深度链接,打开 URL 时可能会出现以下参数:
_dl, _ios_dl, _android_dl, _p
- _ios_dl 和_android_dl 将出现在链接上,如果该链接是在 iOS 和 Android 上生成的深度链接,且每个平台的深度链接值不同。
- 如果 iOS 和 Android 的深度链接值相同,则只显示_dl 。
- 如果在直通参数中传递了其他数据,则会显示_p 。
深度链接处理程序代码示例
应用程序必须有能够解析 openURL 并进行适当处理的处理程序代码。下面的示例演示了如何解析奇异链接参数。
class DeepLinkHandler {
func handleURL(_ url: URL) {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return
}
var params: [String: String] = [:]
// Parse query parameters
if let queryItems = components.queryItems {
for item in queryItems {
switch item.name {
case "_dl":
params["deeplink"] = item.value
case "_ios_dl":
params["ios_deeplink"] = item.value
case "_p":
params["passthrough"] = item.value
default:
break
}
}
}
// Handle the parsed parameters
processDeepLinkParameters(params)
}
private func processDeepLinkParameters(_ params: [String: String]) {
// Process the parameters as needed
print("Processed parameters: \(params)")
}
}
// In SceneDelegate or AppDelegate
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
let handler = DeepLinkHandler()
handler.handleURL(url)
}
class DeepLinkHandler {
fun handleDeepLink(intent: Intent) {
val data: Uri? = intent.data
data?.let { uri ->
val params = mutableMapOf<String, String>()
// Parse query parameters
uri.queryParameterNames?.forEach { name ->
when (name) {
"_dl" -> params["deeplink"] = uri.getQueryParameter(name) ?: ""
"_android_dl" -> params["android_deeplink"] = uri.getQueryParameter(name) ?: ""
"_p" -> params["passthrough"] = uri.getQueryParameter(name) ?: ""
}
}
processDeepLinkParameters(params)
}
}
private fun processDeepLinkParameters(params: Map<String, String>) {
// Process the parameters as needed
println("Processed parameters: $params")
}
}
// In your Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Handle deep link if activity was launched from a deep link
intent?.let { DeepLinkHandler().handleDeepLink(it) }
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Handle deep link if app was already running
intent?.let { DeepLinkHandler().handleDeepLink(it) }
}
}
延迟深度链接支持
安装后首次打开应用程序时,请在向 Singular 报告会话时添加以下参数,以启用延迟深度链接流程:
- install=true
- ddl_enabled=true
Singular 会查看应用程序是否是通过包含延迟深度链接的跟踪链接安装的。如果是,Session 请求会在响应中向服务器返回以下值:
- deferred_deeplink - 深层链接地址。这是您需要解析的内容,以便向用户展示正确的产品或体验。
- deferred_passthrough - 添加到深层链接的任何直通参数。
客户端应用程序应包含代码,以处理 Singular SESSION API 响应中提供的延迟深度链接和直通参数,并适当处理数据。来自 SESSION 通知的带有延迟深度链接值的响应 JSON 将如下所示:
{
"deferred_deeplink":"myapp://deferred-deeplink",
"status":"ok",
"deferred_passthrough":"passthroughvalue"
}
使用动态直通参数
Singular 跟踪链接可以包含动态直通参数(了解更多信息)。如果您的组织已为链接设置了动态直通参数,则深层链接 URL 包括_p 参数,后面跟有 URL 编码的 JSON 字符串值或非结构化字符串,您可以使用这些字符串向用户显示相应的内容或体验。
解决短链接问题
从缩短的 Singular 链接打开应用程序时,应在启动请求中包含以下参数,以通知 Singular 会话端点应将 openuri 参数中发送的 openURL 解析为 Singular 长链接。
- singular_link_resolve_required=true
Singular 将返回未缩短的长链接,应用程序开发人员可以在链接处理程序中解析深链接和直通参数,如前所述。
响应示例
{
"status":"ok",
"resolved_singular_link":"https://myapp.sng.link/A59c0/nha7?_dl=myapp%3A%2F%2Fdeeplink&_ddl=myapp%3A%2F%2Fdeferred-deeplink&_p=passthroughvalue"
}
跨设备支持
在实施 Singular 的跨设备解决方案或将用户与设备级会话关联起来时,有效利用 custom_user_id参数。该参数应包含内部用户 ID,但必须遵守数据隐私政策,避免包含个人身份信息(PII)。
最佳做法是使用从用户名、电子邮件地址或随机生成的字符串中提取的散列值,作为应用程序的唯一用户标识符。通过采用这种方法,您可以让 Singular 利用 custom_user_id用于全面的跨设备报告、用户级数据导出和内部 BI 回传(配置时),从而在维护用户隐私的同时提高分析数据的粒度和价值。
报告收入
Singular可以收集通过应用程序获得的收入数据,帮助分析营销活动的绩效和投资回报率。Singular 将通过报告、导出日志和回传向您提供这些数据。
要跟踪收入事件,请使用与所有事件相同的事件通知端点,但要包含收入参数。
- is_revenue_event 这会将事件标记为收入事件。如果事件名称为__iap__ 或金额大于零,则可以跳过此参数。
- purchase_receipt 这是一个从 Android 或 iOS 的 应用内购买(IAP)流程返回的对象。我们强烈建议将其传递给 Singular,以便为 Singular 提供有关交易的全部详细信息,并通过数据丰富 Singular 报告。
- receipt_signature (仅适用于安卓系统)我们强烈建议将此数据传递给 Singular,以验证交易并打击应用内欺诈行为。
- amt 这是双倍的收入金额(例如:"amt=1.99")。
- cur 这是 ISO 4217 货币代码(例如:"cur=USD")。
使用 "在应用程序客户端代码中实施订阅状态管理"作为指南,从 Google 的 Play Billing Library 和/或 Apple 的 StoreKit 获取购买对象。您还可以直接在设备上查询订阅信息并管理订阅状态。将这些详细信息传回服务器,以便包含在向 Singular 发送的事件请求中。
自定义收入事件示例
import requests
params = {
"a": "sdk_key_here",
"p": "Android",
"i": "com.singular.app",
"ip": "10.1.2.3",
"ve": "9.2",
"aifa": "8ecd7512-2864-440c-93f3-a3cabe62525b",
"asid": "edee92a2-7b2f-45f4-a509-840f170fc6d9",
"n": "RevenueEventName",
"amt": "2.50",
"cur": "USD",
"is_revenue_event": "true",
"purchase_receipt": {
'orderId"': "GPA.1234",
"packageName": "com.example",
"productId": "com.example.product",
"purchaseTime": 1417113074914,
"purchaseState": 0,
"purchaseToken": "hakfcimbkargpM",
},
"receipt_signature": "TyVJfHg8OAoW7W4wuJtasr5agEDMnNXvhfrw==",
"purchase_product_id": "com.example.product",
"purchase_transaction_id": "GPA.1234-1234-1234-12345",
}
response = requests.get("https://s2s.singular.net/api/v1/evt", params=params)
print(response.json())
GET /api/v1/evt
?a=sdk_key_here
&p=Android
&i=com.singular.app
&ip=10.1.2.3
&ve=9.2
&aifa=8ecd7512-2864-440c-93f3-a3cabe62525b
&asid=edee92a2-7b2f-45f4-a509-840f170fc6d9
&n=RevenueEventName
&amt=2.50
&cur=USD
&is_revenue_event=true
&purchase_receipt={"orderId":"GPA.1234","packageName":"com.example","productId":"com.example.product","purchaseTime":1417113074914,"purchaseState":0,"purchaseToken":"hakfcimbkargpM"}
&receipt_signature=TyVJfHg8OAoW7W4wuJtasr5agEDMnNXvhfrw==
&purchase_product_id=com.example.product
&purchase_transaction_id=GPA.1234-1234-1234-12345 HTTP/1.1
Host: s2s.singular.net
Accept: application/json
curl -G "https://s2s.singular.net/api/v1/evt" \
--data-urlencode "a=sdk_key_here" \
--data-urlencode "p=Android" \
--data-urlencode "i=com.singular.app" \
--data-urlencode "ip=10.1.2.3" \
--data-urlencode "ve=9.2" \
--data-urlencode "aifa=8ecd7512-2864-440c-93f3-a3cabe62525b" \
--data-urlencode "asid=edee92a2-7b2f-45f4-a509-840f170fc6d9" \
--data-urlencode "n=RevenueEventName" \
--data-urlencode "amt=2.50" \
--data-urlencode "cur=USD" \
--data-urlencode "is_revenue_event=true" \
--data-urlencode "purchase_receipt={\"orderId\":\"GPA.1234\",\"packageName\":\"com.example\",\"productId\":\"com.example.product\",\"purchaseTime\":1417113074914,\"purchaseState\":0,\"purchaseToken\":\"hakfcimbkargpM\"}" \
--data-urlencode "receipt_signature=TyVJfHg8OAoW7W4wuJtasr5agEDMnNXvhfrw==" \
--data-urlencode "purchase_product_id=com.example.product" \
--data-urlencode "purchase_transaction_id=GPA.1234-1234-1234-12345"
跟踪卸载
Singular 可以使用设备的静默推送通知跟踪卸载情况。要启用此功能,您需要在每次会话通知时向 Singular 服务器发送设备的推送令牌。
-
请务必按照我们的指南在 Singular 平台和您的应用程序中设置卸载跟踪:
- 对于 iOS,将 APNS 令牌附加到 apns_token参数。对于 Android,将 FCM 令牌附加到 fcm参数。
检索 iOS 安装收据
报告 iOS 应用程序的会话时,应在 install_receipt参数中传递安装收据。
要检索此值,请在应用程序中添加以下代码:
// ReceiptManager.h
@interface ReceiptManager : NSObject
+ (nullable NSString *)getInstallReceipt;
@end
// ReceiptManager.m
#import <StoreKit/StoreKit.h>
@implementation ReceiptManager
+ (nullable NSString *)getInstallReceipt {
if (@available(iOS 18.0, *)) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSString *result = nil;
[SKPaymentQueue.defaultQueue addTransactionObserver:[[SKPaymentTransactionObserver alloc] init]];
if (@available(iOS 18.0, *)) {
[AppTransaction.shared fetchWithCompletionHandler:^(AppTransaction *transaction, NSError *error) {
if (error) {
NSLog(@"Failed to get app transaction: %@", error.localizedDescription);
} else {
result = transaction.jwsRepresentation;
}
dispatch_semaphore_signal(semaphore);
}];
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return result;
} else {
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
if (!receiptURL) {
NSLog(@"Receipt URL not found");
return nil;
}
NSError *error = nil;
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL
options:NSDataReadingUncached
error:&error];
if (error) {
NSLog(@"Failed to read receipt: %@", error.localizedDescription);
return nil;
}
return [receiptData base64EncodedStringWithOptions:0];
}
}
@end
import Foundation
import StoreKit
class ReceiptManager {
static func getInstallReceipt() -> String? {
if #available(iOS 18.0, *) {
// Synchronous wrapper for async code
let semaphore = DispatchSemaphore(value: 0)
var result: String?
Task {
do {
let transaction = try await AppTransaction.shared
result = transaction.jwsRepresentation
semaphore.signal()
} catch {
debugPrint("Failed to get app transaction: \(error.localizedDescription)")
semaphore.signal()
}
}
semaphore.wait()
return result
} else {
// Legacy receipt fetching
guard let receiptURL = Bundle.main.appStoreReceiptURL else {
debugPrint("Receipt URL not found")
return nil
}
do {
let receiptData = try Data(contentsOf: receiptURL, options: .uncached)
return receiptData.base64EncodedString(options: [])
} catch {
debugPrint("Failed to read receipt: \(error.localizedDescription)")
return nil
}
}
}
}
遵守数据隐私法
Singular提供隐私保护功能,帮助您与任何可能遵守消费者隐私法(如GDPR和CCPA)的合作伙伴合作。这些合作伙伴希望在最终用户同意共享其私人信息时得到通知。
如果你已经实施了征得用户同意共享其信息的方法,请使用data_sharing_options参数通知 Singular 用户的选择:
- 通过"limit_data_sharing":false 表示用户同意(opted-in)共享其信息。
- 如果用户拒绝,则传入"limit_data_sharing":true 。
Singular在"用户隐私回传"中使用limit_data_sharing ,并将此信息传递给需要的合作伙伴,以遵守相关规定。更多信息请参阅"用户隐私和限制数据共享"。
注意:
- data_sharing_options 参数是可选的,但可能会有一些属性信息,只有在明确通知用户已选择加入的情况下,合作伙伴才会与Singular共享这些信息。