服务器到服务器 - 读取设备数据指南

文档

设备数据检索指南

用于检索平台特定设备标识符和参数的综合指南,这些设备标识符和参数是准确的 S2S API 归因和营销活动测量所必需的。

所需的设备标识符:Singular 要求在所有 API 请求中提供特定的设备标识符,以便准确归因。

移动平台

  • 安卓(Google Play):谷歌广告 ID (GAID/AIFA) 和应用程序集 ID (ASID)
  • 安卓(亚马逊):用于 Fire 设备的亚马逊广告 ID (AMID)
  • 安卓(中国 OEM):开放广告 ID (OAID),适用于无 Google Play 服务的设备
  • 安卓(回退):安卓 ID (ANDI) 仅在无其他可用标识符时使用
  • iOS:供应商标识符 (IDFV) 和广告商标识符 (IDFA) 可用时

设备参数:移动平台所需的地域、设备制造商、设备型号和构建版本

下面的代码示例演示了每种平台和标识符类型的检索方法。


应用示例

参考实现

展示设备数据检索模式的 iOS 和 Android 完整工作示例。


iOS 设备标识符

iOS 设备需要 IDFV(始终)和 IDFA(当用户授予跟踪权限时)以及 ATT 授权状态,以便准确归属。

所需的 iOS 标识符

标识符要求

  • IDFV:所有 S2S 请求都需要,无论跟踪权限如何
  • IDFA:如果用户同意应用跟踪透明度,则应提供
  • ATT 状态:所有请求都需要的授权状态代码(0-3)

实施指南

如何检索 iOS 设备数据
#

广告商识别码 (IDFA)

广告商识别码 (IDFA) 使广告商能够跟踪用户操作(广告点击、应用安装)并将其归属于特定广告系列,从而实现精准定位和优化。

从 iOS 14.5 开始,用户必须在应用程序访问 IDFA 之前通过应用程序跟踪透明度 (ATT) 框架进行选择。未经用户同意,IDFA 将返回所有 0,从而限制了跟踪功能。


供应商标识符 (IDFV)

供应商标识符 (IDFV) 是 Apple 分配给设备的唯一标识符,特定于供应商/开发者。在设备上来自同一供应商的所有应用程序中保持一致,无需个人身份识别即可实现跨应用程序行为跟踪。

实施步骤

  • 确保在尝试访问 IDFA 之前显示并处理 ATT 提示
  • 捕获 IDFA(如果已授权)并传递给服务器以进行 API 请求
  • 捕获 IDFV 并传递给服务器以进行 API 请求(始终需要
  • 在所有请求中包含 ATT 授权状态

代码示例

请求 ATT 授权并检索 IDFA/IDFV

OBJECTIVE-CSWIFT
#import <AdSupport/AdSupport.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <UIKit/UIKit.h>

- (void)retrieveIdentifiers {
    // Request ATT authorization (iOS 14.5+)
    [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        dispatch_async(dispatch_get_main_queue(), ^{
            switch (status) {
                case ATTrackingManagerAuthorizationStatusAuthorized: {
                    // ATT authorized, retrieve IDFA
                    NSUUID *idfa = [[ASIdentifierManager sharedManager] advertisingIdentifier];
                    NSLog(@"IDFA: %@", [idfa UUIDString]);
                    NSLog(@"ATT Status: %ld", (long)status); // Status = 3
                    break;
                }
                case ATTrackingManagerAuthorizationStatusDenied:
                    NSLog(@"ATT Status: Denied (%ld)", (long)status); // Status = 2
                    break;
                case ATTrackingManagerAuthorizationStatusRestricted:
                    NSLog(@"ATT Status: Restricted (%ld)", (long)status); // Status = 1
                    break;
                case ATTrackingManagerAuthorizationStatusNotDetermined:
                    NSLog(@"ATT Status: Not Determined (%ld)", (long)status); // Status = 0
                    break;
                default:
                    NSLog(@"Unknown ATT status.");
                    break;
            }

            // Retrieve IDFV (always available)
            NSUUID *idfv = [[UIDevice currentDevice] identifierForVendor];
            if (idfv != nil) {
                NSLog(@"IDFV: %@", [idfv UUIDString]);
            } else {
                NSLog(@"Unable to retrieve IDFV.");
            }
        });
    }];
}

// Call the method to retrieve identifiers
[self retrieveIdentifiers];

标识符可用性

  • IDFA:需要 iOS 14.5 以上版本的 ATT 授权。未经同意,返回全零
  • IDFV:始终可用--包含在所有 Singular API 请求中
  • ATT 状态值:0=未确定,1=受限,2=拒绝,3=授权

安卓设备标识符(Google Play)

使用 Google Play 服务的安卓设备要求在所有请求中提供应用程序集 ID (ASID),并在可用时提供 Google 广告 ID (GAID/AIFA)。

所需的 Google Play 标识符

标识符要求

  • ASID:Google Play 设备的所有 S2S 请求都需要
  • AIFA/GAID:可用时应提供(不可选择不提供

实施指南

如何检索 Android 设备数据(Google Play)
#

谷歌广告标识符 (GAID)

谷歌广告标识符 (GAID),也称为 AIFA 或 Android Advertising ID (AAID),是分配给 Android 设备的唯一、用户可重置的标识符。 它使广告商和开发商能够跟踪和归因用户在应用程序中的操作,以便在维护隐私的同时进行广告定位和优化。

JAVAKOTLIN

依赖关系

build.gradle 中添加所需的依赖关系:

dependencies {
    implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
}

权限

如果针对 Android 12/API 31+ 级,请在AndroidManifest.xml 中添加权限:

<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

使用

AdIdUtils.getGoogleAdId(getApplicationContext());

实现

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;

public class AdIdUtils {

    public static void getGoogleAdId(Context context) {
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
                    
                    String adId = adInfo.getId();
                    boolean isLimitAdTrackingEnabled = adInfo.isLimitAdTrackingEnabled();
                    
                    Log.d("GoogleAdID", "Advertising ID: " + adId);
                    Log.d("GoogleAdID", "Limit Ad Tracking: " + isLimitAdTrackingEnabled);
                } catch (Exception e) {
                    Log.e("GoogleAdID", "Error retrieving GAID", e);
                }
            }
        });
    }
}

应用程序集 ID (ASID)

Android 应用程序集 ID 为同一开发者提供具有隐私意识的跨应用程序跟踪功能,可用于分析和防止欺诈,但不能用于个性化广告。

JAVAKOTLIN

依赖关系

dependencies {
    implementation 'com.google.android.gms:play-services-appset:16.1.0'
}

使用方法

AppSetIdUtils.getAppSetId(getApplicationContext());

实现

import android.content.Context;
import android.util.Log;
import com.google.android.gms.appset.AppSet;
import com.google.android.gms.appset.AppSetIdClient;
import com.google.android.gms.appset.AppSetIdInfo;
import com.google.android.gms.tasks.Task;

public class AppSetIdUtils {

    public static void getAppSetId(Context context) {
        AppSetIdClient client = AppSet.getClient(context);
        Task task = client.getAppSetIdInfo();

        task.addOnSuccessListener(info - {
            String appSetId = info.getId();
            int scope = info.getScope();

            Log.d("AppSetID", "App Set ID: " + appSetId);
            Log.d("AppSetID", "Scope: " + (scope == AppSetIdInfo.SCOPE_DEVELOPER ? "Developer" : "App"));
        }).addOnFailureListener(e - {
            Log.e("AppSetID", "Failed to retrieve App Set ID", e);
        });
    }
}

安卓设备标识符(非 Google Play)

没有 Google Play 服务的安卓设备需要根据设备制造商和分发方式提供其他标识符。

亚马逊设备标识符

AMID:对于没有 Google Play 服务的 Amazon Fire 设备,应提供 Amazon Advertising ID。

如何检索亚马逊广告 ID (AMID)
#

亚马逊标识符 (AMID)

亚马逊广告标识符可在没有 Google Play 服务的亚马逊 Fire 设备上实现用户可重置的广告跟踪,在维护用户隐私的同时实现归因。

要求

  • 适用于运行 Fire OS 5.1+ 的亚马逊 Fire 设备
  • 尊重用户的 "限制广告跟踪 "偏好
  • 可能不适用于非 Fire OS 设备
JAVAKOTLIN

使用方法

AdvertisingIdHelper.getAmazonAdvertisingId(getContentResolver());

实施

import android.content.ContentResolver;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;

public class AdvertisingIdHelper {

    public static void getAmazonAdvertisingId(ContentResolver contentResolver) {
        String advertisingID = "";
        boolean limitAdTracking = false;

        try {
            limitAdTracking = Settings.Secure.getInt(contentResolver, "limit_ad_tracking") != 0;
            advertisingID = Settings.Secure.getString(contentResolver, "advertising_id");

            Log.d("AdvertisingID", "Amazon Advertising ID: " + advertisingID);
            Log.d("LimitAdTracking", "Limit Ad Tracking: " + limitAdTracking);

        } catch (SettingNotFoundException e) {
            Log.e("AdvertisingID", "Advertising ID not supported on this device", e);
        }
    }
}

中文 OEM 识别码

OAID:应为没有 Google Play 服务的中国制造设备提供开放式广告标识符。

如何检索开放广告标识符(OAID)
#

开放广告标识符 (OAID)

开放广告标识符(OAID)是用于在中国制造的安卓设备上发布广告的唯一匿名标识符。由移动安全联盟(MSA)推出,用于替代无法使用 Google Play 服务的设备上的 GAID。

支持的设备:华为、小米、OPPO、vivo 和其他中国制造的安卓设备

通过MSA SDK或华为移动服务 (HMS) 访问。

JAVAKOTLIN

依赖关系

dependencies {
    implementation 'com.bun.msa.sdk:msa:1.0.26'
}

执行

import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.bun.msa.sdk.DeviceId;
import com.bun.msa.sdk.DeviceIdSupplier;
import com.bun.msa.sdk.IIdentifierListener;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "OAIDExample";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getOAID();
    }

    private void getOAID() {
        try {
            DeviceId deviceId = new DeviceId(this);
            deviceId.getDeviceIds(new IIdentifierListener() {
                @Override
                public void onSupport(boolean isSupport, DeviceIdSupplier supplier) {
                    if (isSupport && supplier != null) {
                        String oaid = supplier.getOAID();
                        Log.d(TAG, "OAID: " + oaid);
                    } else {
                        Log.e(TAG, "OAID not supported on this device");
                    }
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "Error retrieving OAID", e);
        }
    }
}

安卓 ID 回退

ANDI 限制:只有在没有其他可用标识符且应用程序未通过 Google Play Store 发布的情况下,才能提供 Android ID。 禁止用于 Google Play 应用程序。

如何检索 Android ID (ANDI)
#

Android ID (ANDI)

安卓 ID 是设备首次设置时生成的唯一 64 位标识符。 从安卓 8.0(奥利奥)开始,按应用程序和用户范围设置,不同的应用程序会收到不同的安卓 ID,除非它们共享相同的签名密钥。

持久性:除非设备出厂重置或 OTA 更新后卸载/重新安装应用程序,否则保持不变。

JAVAKOTLIN
import android.provider.Settings;
import android.content.Context;

String androidId = Settings.Secure.getString(
    context.getContentResolver(), 
    Settings.Secure.ANDROID_ID
);

网络和跨平台标识符

网络应用程序和跨平台实施需要奇异设备 ID (SDID),以便进行准确的归属跟踪。

所需网络标识符

SDID:Web、PC、控制台和 CTV 平台的所有 S2S 请求都需要单一设备 ID。

如何检索单一设备 ID (SDID)
#

奇异网络 SDK 设备 ID

奇异设备 ID (SDID) 为网络应用程序和非移动平台提供一致的跨会话跟踪。

前提条件:在检索 SDID 之前,必须先实施并初始化 Singular Web SDK。

使用方法

// Retrieve SDID after Singular SDK initialization
const sdid = window.singularSdk.getSingularDeviceId();
console.log("Singular Device ID:", sdid);

实施注意事项:只有在 Singular SDK 成功初始化后才能调用getSingularDeviceId(),在初始化前尝试检索将返回空。


移动设备参数

所需的设备参数为移动平台上的归因和分析提供了重要的上下文。

所需参数

移动平台:iOS和Android的所有S2S请求都要求提供Locale、Device Make、Device Model和Build。

如何检索设备参数
#

参数检索

收集地域、制造商、型号和构建信息,以进行完整的设备剖析。

OBJECTIVE-CSWIFTJAVAKOTLIN
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <sys/sysctl.h>

// Retrieve Locale
NSString *retrieveLocale() {
    NSString *locale = [[NSLocale currentLocale] localeIdentifier];
    NSLog(@"Locale: %@", locale);
    return locale;
}

// Retrieve Manufacturer (always Apple for iOS)
NSString *retrieveManufacturer() {
    return @"Apple";
}

// Retrieve Device Model
NSString *deviceModel() {
    size_t bufferSize = 64;
    char model[bufferSize];
    int status = sysctlbyname("hw.machine", model, &bufferSize, NULL, 0);
    
    if (status == 0) {
        NSString *deviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
        NSLog(@"Device Model: %@", deviceModel);
        return deviceModel;
    } else {
        NSLog(@"Unable to retrieve device model.");
        return nil;
    }
}

// Retrieve Build Version
NSString *buildVersion() {
    size_t bufferSize = 64;
    char build[bufferSize];
    int status = sysctlbyname("kern.osversion", build, &bufferSize, NULL, 0);
    
    if (status == 0) {
        NSString *buildVersion = [NSString stringWithCString:build encoding:NSUTF8StringEncoding];
        NSLog(@"Build Version: %@", buildVersion);
        return buildVersion;
    } else {
        NSLog(@"Unable to retrieve build version.");
        return nil;
    }
}

参数映射

  • 地域 (lc):语言和地区代码(如 en_US、zh_CN
  • 制造商 (ma):设备制造商(苹果、三星、小米
  • 型号 (mo):具体设备型号(iPhone14,2、SM-G991B
  • 版本 (bd):前缀为 "Build/"的操作系统构建版本