注: 服务器到服务器集成仅可根据要求提供。请 联系您的 Singular 客户服务经理或 Singular 支持部门。
Singular SDK 必须嵌入到你的应用程序中,作为Singular SDK的替代方案,Singular还提供了一个REST API,可用于构建一个从你自己的服务器运行的完整集成。
本指南介绍如何使用 Singular 构建基本的 S2S 集成,并实现各种可选功能。
有关 S2S API 端点、参数和调用示例的完整列表,请参阅《S2S 端点参考》。
基本集成
与 Singular 的最基本集成包括在有新会话时通知 Singular,换句话说,就是在应用程序打开时通知 Singular。
要通知 Singular 有关用户会话的信息,请调用会话通知端点。
会话通知允许 Singular 做几件事:
- 如果这是应用程序在特定设备上的首次会话,Singular 会识别新安装并触发安装归因流程。
- 如果会话符合重新参与会话的条件,Singular 会触发重新参与归因流程(在重新参与常见问题中了解更多信息)。
- 否则,Singular 会将其标记为会话,用于跟踪用户活动和保留情况。
会话通知端点有一些必要参数。如需获取报告会话所需的全部数据,请参阅参考资料:检索 iOS 安装收据和参考资料:检索设备标识符和会话数据。
小提示 在收集数据以报告会话时,请务必等待异步函数返回并处理各种边缘情况。 这是一个常见问题,可能导致数据丢失和部分归属。
收集和发送应用程序集 ID(Android 12+ 需要)
应用程序集 ID或ASID是一个新的隐私友好型 ID,用于 Android 12+ 设备。设备上由同一开发者在 Google Play 商店发布的所有应用程序都共享 App Set ID。
将应用程序集合 ID 作为参数添加到会话调用和每个事件调用中,与发送 GAID 的方式类似。
。
要收集应用程序集 ID,请在应用程序中使用以下代码:
Context context = getApplicationContext();
AppSetIdClient client = AppSet.getClient(context);
Task<AppSetIdInfo> task = client.getAppSetIdInfo();
task.addOnSuccessListener(new OnSuccessListener<AppSetIdInfo>() {
@Override
public void onSuccess(AppSetIdInfo info) {
// 确定 Android Appset ID 的当前范围。
int scope = info.getScope();
// 读取Android Appset ID值,它使用UUID版本4格式。
String id = info.getId();
}
});
重要:发送 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 指定 "Service"。 clickTimestampSeconds 从 Play Install Referrer API 接收到的点击时间戳(例如,"1550420123")。 installBeginTimestampSeconds 从 Play Install Referrer API 接收到的安装开始时间。 current_device_time 以毫秒为单位的当前设备时间(例如 "1550420454906")。
以下是报告安装推荐人事件的示例代码:
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
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
可选:发送用户 ID
通知 Singular 一个新会话时,可以添加用户 ID。用户 ID 可以是用户名、电子邮件地址、随机生成的字符串,也可以是应用程序用作用户 ID 的任何标识符。Singular 将在用户级数据导出和内部 BI 回传(如果配置了)中使用用户 ID。
要发送用户 ID,请在调用会话通知端点时添加 "custom_user_id "参数。
例如
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
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': 'player_id_1234'
}
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&n=MyCoolApp&dnt=0&c=wifi&cn=Comcast&lc=en_US&bd=Build%2FMMB29K&ma=samsung&mo=SM-G935F&custom_user_id=player_id_1234
curl --request GET \
--url '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&n=MyCoolApp&dnt=0&c=wifi&cn=Comcast&lc=en_US&bd=Build%2FMMB29K&ma=samsung&mo=SM-G935F&custom_user_id=player_id_1234'
附加归因处理
苹果搜索广告系列的归因(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) {
// 将 iAd 归因详细信息从应用程序发送到您的服务器。
}
}];
}
}
- 在检索归因数据前设置几秒钟的延迟。
- 如果响应为 "False "或错误代码(0、2、3),则执行重试逻辑。2 秒后再次调用 Apple Attribution API。
2.将归因数据发送给 Singular:
要与 Singular 共享归因数据,请使用 "事件通知"(EventNotification)端点报告保留事件名称为__iAd_Attribution__ 的事件。将上一步中获取的 JSON 对象作为e 参数 的值传入,如下例所示。
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
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) {
// 将 AdServices AttributionToken 从应用程序发送到您的服务器。
}
}
备注:
- 属性令牌在设备上生成。
- 生成后,令牌会在设备上缓存 5 分钟。 5 分钟后,如果调用 attributionToken(),就会生成一个新令牌。
- 生成的标记有效期为 24 小时。
2.将归属令牌发送给 Singular:
对令牌进行URL编码,并通过会话通知端点将令牌发送给Singular,同时附加&attribution_token=参数。 在每次安装和重新安装后的第一次会话中都应发送该令牌,以便Singular跟踪苹果搜索广告的下载和重新下载情况。
元安装推荐人归因(安卓)
"元推荐人 "是 Facebook 推出的安卓专用测量解决方案,允许广告商访问安卓应用程序安装的细粒度用户级归因数据(请参阅 Facebook 的数据政策)。它由实施 "Google Play 安装推荐人"(请参阅 "传递 Google 安装推荐人")和 "元安装推荐人 "技术组成,用于测量应用程序的安装情况。有关元推荐人的更多信息,请参阅常见问题。。
与 Singnular 共享 Meta Install Referrer 信息:
- 首次打开应用程序时,根据Meta 文档检索 Meta 安装 Referrer。
-
使用会话通知端点(Session Notification endpoint)向Singular报告会话,包括参数meta_ref。该参数为 JSON 编码,具有以下属性:
属性 属性 is_ct 从 Meta Install Referrer 接收到的 "is_ct "值。(例如 0 或 1) install_referrer 从 Meta 安装推荐器接收到的 "install_referrer "值 actual_timestamp 从 Meta Install Referrer 接收到的 "actual_timestamp "值(如 1693978124)。
跟踪事件
Singular 可以收集应用内事件的相关数据,帮助分析营销活动的效果。事件可包括任何用户交互,从登录和注册到游戏应用中的等级提升。
在实施与 Singular 的 SDK/S2S 集成之前,您应该有一份贵组织希望跟踪的事件列表(请参阅定义应用程序内事件)。
要在应用程序中发生事件时通知 Singular,请调用事件通知端点。 您在调用中包含的事件名称将在 Singular 报告、导出和回传中被识别。
注意:
- Singular 建议使用Singular 的标准事件和属性命名约定传递事件。 使用标准事件可简化映射,并在集成中与合作伙伴的标准事件兼容。
- 我们强烈建议使用英文传递事件名称和其他属性,以便与第三方合作伙伴和分析解决方案兼容。
- 事件名称限制为 32 个 ASCII 字符。对于非 ASCII 字符,转换为 UTF-8 后限制为 32 字节。
- 事件属性和值限制为 500 个 ASCII 字符。
跟踪收入
Singular可以收集通过应用程序获得的收入数据,以帮助分析营销活动的效果和投资回报率。Singular会通过报告、日志导出和回传等方式向您提供这些数据。
要跟踪收入事件,请使用与所有事件相同的事件通知端点,但要添加以下信息:
- is_revenue_event=true:这会将事件标记为收入事件。如果事件名称是 __iap__ 或金额大于零,可以跳过此参数。
- 购买收据:这是从 Android 或 iOS 的应用内购买(IAP)流程返回的对象。我们强烈建议将其传递给 Singular,以便为 Singular 提供有关交易的全部详细信息,并通过数据丰富您的 Singular 报告。
- 购买签名(仅限 Android): 我们强烈建议将此数据传递给 Singular,以验证交易并打击应用内欺诈行为。
- 收入金额(例如,"amt=1.99")。
- 货币(使用 ISO 4217货币代码,例如 "cur=USD")。
检索购买收据
收入事件发生后,以下是获取购买收据以便发送给 Singular 的方法:
- 在安卓系统中:Google Play 提供了一个 API,用于获取购买收据("应用内购买数据")和购买签名("应用内数据签名")。请使用getBuyIntent()方法。
- 在 iOS 系统中:如下例所示,使用 Apple 的应用内购买 API(更多信息,请参阅Apple 应用内购买 API)。
// SKPaymentTransactionObserver
+ (void)paymentQueue:(id)queue updatedTransactions:(NSArray *)skTransactions {
NSString *transactionReceipt = nil;
if ([skTransaction respondsToSelector:@selector(transactionReceipt)]) {
NSData *transactionReceiptRaw = [skTransaction performSelector:@selector(transactionReceipt)];
if (transactionReceiptRaw) {
transactionReceipt = [ApUtils base64Encode:transactionReceiptRaw];
}
}
}
自定义收入事件示例
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
EVENT_URL = 'https://s2s.singular.net/api/v1/evt'
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',
'bd': 'Build/13D15',
'aifa': '8ecd7512-2864-440c-93f3-a3cabe62525b',
'utime': 1483228800,
'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':'hakfcimbk... pM'},
'receipt_signature': 'TyVJfHg8OAoW7W4wuJt...5agEDMnNXvhfrw==',
'purchase_product_id': 'com.example.product',
'purchase_transaction_id': 'GPA.1234-1234-1234-12345'
}
result = requests.get(EVENT_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/evt?n=RevenueEventName&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&amt=2.50&cur=EUR&bd=Build%2F13D15&is_revenue_event=true&purchase_receipt=%7B%27orderId%27%3A%27GPA.1234%27%2C%27packageName%27%3A%27com.example%27%2C%27productId%27%3A%27com.example.product%27%2C%27purchaseTime%27%3A1417113074914%2C%27purchaseState%27%3A0%2C%27purchaseToken%27%3A%27hakfcimbk...%20pM%27%7D&receipt_signature=TyVJfHg8OAoW7W4wuJt5agEDMnNXvhfrw==&purchase_product_id=com.example.product&purchase_transaction_id=GPA.1234-1234-1234-12345https://s2s.singular.net/api/v1/evt?n=RevenueEventName&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&amt=2.50&cur=EUR&bd=Build%2F13D15
curl --request GET \ --url 'https://s2s.singular.net/api/v1/evt?n=RevenueEventName&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&amt=2.50&cur=EUR&bd=Build%2F13D15&is_revenue_event=true&purchase_receipt=%7B%27orderId%27%3A%27GPA.1234%27%2C%27packageName%27%3A%27com.example%27%2C%27productId%27%3A%27com.example.product%27%2C%27purchaseTime%27%3A1417113074914%2C%27purchaseState%27%3A0%2C%27purchaseToken%27%3A%27hakfcimbk...%20pM%27%7D&receipt_signature=TyVJfHg8OAoW7W4wuJt5agEDMnNXvhfrw==&purchase_product_id=com.example.product&purchase_transaction_id=GPA.1234-1234-1234-12345'
支持深度链接
深度链接是指向应用程序内特定内容的链接。当用户在安装了应用程序的设备上点击深层链接时,应用程序就会打开并显示特定的产品或体验。
奇异跟踪链接可包括深度链接和延迟深度链接(更多信息,请参阅我们的 深度链接常见问题和奇异链接常见问题)。
深度链接的先决条件
对于 iOS:
- 在 Singular 的链接管理页面为链接配置至少一个子域。更多信息,请参阅 Singular链接常见问题解答。
- 根据 SDK 文档启用通用链接。
- 在应用程序代码中实施链接处理程序(请参阅 SDK 文档中的处理程序)。
针对 Android:
- 根据 SDK 文档配置 Android 深度链接。
- 在应用程序代码中实施链接处理程序(请参阅 SDK 文档中的处理程序)。
支持深度链接
无论何时通过深度链接打开应用程序,在向 Singular 报告会话时都要使用openuri参数添加 URL。使用 Singular 链接时需要这样做。
启用延迟深度链接
安装后首次打开应用程序时,请在向 Singular 报告会话时添加以下参数,启用延迟深度链接流程:
- install=true
- ddl_enabled=true
Singular 会查看应用程序是否是通过包含延迟深度链接的跟踪链接安装的。如果是,调用将返回以下值:
- deferred_deeplink- 深度链接地址。这是您需要解析的内容,以便向用户展示正确的产品或体验。
- deferred_passthrough- 添加到深层链接的任何直通参数。
支持延迟深度链接的会话通知调用示例
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
params = {
'a': SDK_KEY,
'p': 'iOS',
'i': '162738612',
'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,
'dnt': 0,
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'openuri':'https://myapp.sng.link/A59c0/nha7?_dl=myapp%3A%2F%2Fdeeplink&_ddl=myapp%3A%2F%2Fdeferred-deeplink&_p=passthroughvalue',
'install':'true',
'ddl_enabled':'true'
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
响应示例
{
"deferred_deeplink":"myapp://deferred-deeplink",
"status":"ok",
"deferred_passthrough":"passthroughvalue"
}
处理奇异短链接
从Singular 短链接打开应用程序时,应在启动请求中发送以下参数,以通知 Singular 端点 openuri 中发送的 url 应解析为 Singular 长链接。
- singular_link_resolve_required=true
Singular 会返回长链接,应用程序开发人员可以在链接处理程序中解析深链接和直通参数。
使用短链接解析的会话通知调用示例
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
params = {
'a': SDK_KEY,
'p': 'iOS',
'i': '162738612',
'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,
'dnt': 0,
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'openuri':'https://myapp.sng.link/A59c0/nha7/q5a2',
'singular_link_resolve_required':'true',
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
响应示例
{
"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 跟踪链接可包含动态直通参数(了解更多信息)。 如果您的组织已为链接设置了动态直通参数,则深层链接 URL 会包含_p参数,其后是 URL 编码的 JSON 值或非结构化字符串,您可使用这些参数向用户显示相应的内容或体验。 。
高级选项
Singular S2S 集成支持以下高级功能。这些功能使用上述相同的 API 端点实现,但有特殊的参数和要求。
跟踪卸载
Singular 可以使用设备的静默推送通知跟踪卸载情况。要启用该功能,您需要在每次会话通知时向 Singular 服务器发送设备的推送令牌。
在安卓系统中跟踪卸载
要在安卓系统中启用卸载跟踪功能,首先要调用 FirebaseInstanceId.getInstance().getToken() 从应用程序中获取 FCM 令牌。如果令牌尚未生成,该方法将返回空值。有关详细信息,请参阅Google Firebase 文档。
然后在向 Singular 报告会话时在fcm参数中传递设备令牌,如下例所示:
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
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,
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'fcm': 'bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1'
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/launch?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&n=MyCoolApp&c=wifi&cn=Comcast&bd=Build%2F13D15&fcm=bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1
curl --request GET \
--url 'https://s2s.singular.net/api/v1/launch?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&n=MyCoolApp&c=wifi&cn=Comcast&bd=Build%2F13D15&fcm=bk3RNwTe3H0CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1'
跟踪 iOS 中的卸载
Singular 可以通过苹果的推送通知跟踪 iOS 上的卸载情况。如果你的应用程序还不支持推送通知,请参阅Apple 的指南。 一旦你的应用程序支持推送通知,在向 Singular 报告会话时,请传递从 APNS 返回的设备令牌。
注意:
- 我们假设你已经有了推送通知的实现,并从中获取了设备令牌。
- APNS 令牌通常是本地形式的二进制数据。请按照从 APNS 收到的方式将其传递给 Singular。如果您的应用程序出于其他目的更改令牌数据类型,请确保以十六进制编码字符串的形式传递,例如:encodedb0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052
import requests
import json
SDK_KEY = '[开发人员工具 > SDK 集成 > SDK 密钥中的 sdk_key]。'
LAUNCH_URL = 'https://s2s.singular.net/api/v1/launch'
params = {
'a': SDK_KEY,
'p': 'iOS',
'i': '162738612',
'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,
'dnt': 0,
'n': 'MyCoolApp',
'c': 'wifi',
'cn': 'Comcast',
'bd': 'Build/13D15',
'apns_token': 'b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052'
}
result = requests.get(LAUNCH_URL, params=params)
print result.json()
https://s2s.singular.net/api/v1/launch?a=SDK_KEY&p=iOS&i=162738612&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&dnt=0&n=MyCoolApp&c=wifi&cn=Comcast&bd=Build%2F13D15&apns_token=b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052
curl --request GET \
--url 'https://s2s.singular.net/api/v1/launch?a=SDK_KEY&p=iOS&i=162738612&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&dnt=0&n=MyCoolApp&c=wifi&cn=Comcast&bd=Build%2F13D15&apns_token=b0adf7c9730763f88e1a048e28c68a9f806ed032fb522debff5bfba010a9b052'
遵守数据隐私法
Singular提供隐私保护功能,帮助您与任何可能遵守消费者隐私法(如GDPR和CCPA)的合作伙伴合作。这些合作伙伴希望在最终用户同意共享其私人信息时得到通知。
如果你已经实施了一种征求用户同意共享其信息的方法,请使用data_sharing_options参数通知 Singular 用户的选择:
- 传递"limit_data_sharing":false,表示用户同意(选择加入)共享其信息。
- 如果用户拒绝,则传递"limit_data_sharing":true。
Singular会在"用户隐私回传"(User Privacy Postbacks)中使用limit_data_sharing,并将此信息传递给需要的合作伙伴,以遵守相关规定。更多信息请参阅"用户隐私和限制数据共享"。
注意:
- 该方法的使用是可选的,但可能会有归属信息,只有在明确通知用户已选择加入的情况下,合作伙伴才会与Singular共享这些信息。
- 如果在GET请求中传递JSON对象,请记得对其进行URL编码。
字段 | 类型 | 说明 | 使用方法 |
limit_data_sharing | boolean |
在每个 "launch "或 "evt "请求中传递这个可选值,以显示最终用户的偏好。 |
data_sharing_options= |
参考:检索 iOS 安装收据
正如会话通知端点参考中所述,在报告 iOS 应用程序的会话时,应在install_receipt参数中传递安装收据。
要获取该值,请在应用程序中添加以下代码:
+ (NSString*)installReceipt {
// install receipts are iOS 7.0+
if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_7_0) {
return nil;
}
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
if (receiptURL) {
NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
if (receipt) {
return [receipt base64EncodedStringWithOptions:0];
}
}
return nil;
}
参考:检索设备标识符和会话数据
本节将详细介绍如何检索 REST API 所需的某些值。这些值是行业标准,Apple 和 Google 也有相关文档。为方便起见,我们提供了一些参考实现。
检索谷歌广告 ID/限制广告跟踪(安卓标识符)
在应用程序中获取广告 ID 需要使用 Google Play Services SDK。 在 AndroidManifest.xml 中添加以下标签作为应用程序元素的子元素:
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
如果您的应用程序针对 Android 12/API level 31 或更高版本,请添加访问 Google Advertising ID 的权限:
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
获取 Google 广告 ID/限制广告跟踪参数的示例代码:
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
import com.google.android.gms.common.GooglePlayServicesAvailabilityException;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import java.io.IOException;
// 不要从主线程调用此函数。 否则,将抛出 IllegalStateException。
public void getIdAndLAT() {
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException e) {
// 连接到 Google Play 服务时出现不可恢复的错误(例如,旧版本的服务不支持获取 AdvertisingId)。
} catch (GooglePlayServicesAvailabilityException e) {
// 连接到 Google Play 服务时遇到可恢复的错误。
} catch (GooglePlayServicesNotAvailableException e) {
// Google Play 服务不完全可用。
}
final String GAID = adInfo.getId();
final boolean limitAdTracking = adInfo.isLimitAdTrackingEnabled();
}
检索 Android 的地域、设备和构建
// Locale - lc= query parameter
String locale = Locale.getDefault();
// Model - mo= query parameter
String device = Build.MODEL;
// Build - bd= query parameter
String build = "Build/" + Build.ID;
检索 App Tracking Transparency 授权状态 (iOS)
从 iOS 14.5 开始,需要使用 App Tracking Transparency 来检索设备的 IDFA。如果显示 App Tracking Transparency 提示,请务必在尝试检索 IDFA 之前执行该提示和处理程序。
下面是一个示例,说明如何实现 ATT 提示(可选)以及如何检索 ATT 授权规约(必选):
#import <AppTrackingTransparency/ATTrackingManager.h>
// 如果您决定显示 ATT 提示,则可选。 显示提示并处理值。 即使多次调用也只会出现一次。
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status){
// your authorization handler here
}];
// 必需读取当前 ATT 授权状态
ATTrackingManagerAuthorizationStatus status = [ATTrackingManager trackingAuthorizationStatus];
检索 IDFA/限制广告跟踪(iOS 标识符)
从 iOS 14.5 开始,检索 IDFA 需要App Tracking Transparency。如果您决定显示 App Tracking Transparency 提示,请确保在尝试检索 IDFA 之前执行该提示和处理程序。
如果不打算显示应用程序跟踪透明度,仍可检索 IDFA(值将为零)。在任何情况下都必须检索并发送 IDFV,因为如果 IDFA 不可用或全为零,Singular 就会返回 IDFV。
iOS 13 及以下版本需要使用 limit-ad-track (isAdvertisingTrackingEnabled) 标志,用于显示用户是否选择退出广告跟踪。对于 iOS 14 及以上版本,该标记已被弃用,如果被检索到,则是一个静态值。Singular 和合作伙伴将依赖较新的ATT 授权状态值来处理隐私流的数据。
以下是检索 IDFA、IDFV 和限制广告跟踪状态的示例:
// 在文件顶部导入 AdSupport 类
@import AdSupport;
// 在文件顶部导入 AdSupport 类@import AdSupport;
获取 IDFA/限制广告跟踪参数的示例代码:
NSString* IDFA = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSString* IDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
BOOL isAdvertisingTrackingEnabled = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];
Class AdSupportClass = NSClassFromString(@"ASIdentifierManager");
id sharedManager = nil;
if (AdSupportClass && [AdSupportClass respondsToSelector:@selector(sharedManager)]) {
sharedManager = [AdSupportClass performSelector:@selector(sharedManager)];
}
if (sharedManager) {
NSString* IDFA = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSString* IDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
BOOL dnt = ![[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];
}
检索 iOS 的 Locale、Device 和 Build
// Locale - lc= query parameter
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
// Model - mo= query paramter
#import <sys/sysctl.h>
NSString *device() {
size_t bufferSize = 64;
NSMutableData * buffer = [[NSMutableData alloc] initWithLength:bufferSize];
int status = sysctlbyname("hw.machine", buffer.mutableBytes, &bufferSize, NULL, 0);
if (status != 0) {
return nil;
}
return [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
}
// Build - bd= query parameter
NSString * build () {
size_t bufferSize = 64;
NSMutableData *buffer = [[NSMutableData alloc] initWithLength:bufferSize];
int status = sysctlbyname("kern.osversion",buffer.mutableBytes, &bufferSize, NULL, 0);
if (status != 0) {
return nil;
}
return [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
}
// Locale - lc= query parameter
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
// Model - mo= query paramter
@import Darwin.sys.sysctl;
NSString *device(void) {
size_t bufferSize = 64;
NSMutableData * buffer = [[NSMutableData alloc] initWithLength:bufferSize];
int status = sysctlbyname("hw.machine", buffer.mutableBytes, &bufferSize, NULL, 0);
if (status != 0) {
return nil;
}
return [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
}
// Build - bd= query parameter
@import Darwin.sys.sysctl;
NSString * build ( void ) {
size_t bufferSize = 64;
NSMutableData *buffer = [[NSMutableData alloc] initWithLength:bufferSize];
int status = sysctlbyname("kern.osversion",buffer.mutableBytes, &bufferSize, NULL, 0);
if (status != 0) {
return nil;
}
return [[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding];
}