デバイスデータ取得ガイド
正確なS2S APIアトリビューションとキャンペーン測定に必要なプラットフォーム固有のデバイス識別子とパラメータを取得するための包括的なガイドです。
必要なデバイス識別子Singularでは、正確なアトリビューションのために、全てのAPIリクエストに特定のデバイス識別子を要求しています。
モバイルプラットフォーム
- Android(Google Play):Google Advertising ID (GAID/AIFA)とApp Set ID (ASID)
- Android(Amazon):Fire デバイス用の Amazon Advertising ID (AMID)
- Android(中国OEM):Google Playサービス非対応端末向けOpen Advertising ID(OAID)
- Android(フォールバック):Android ID(ANDI):他の識別子が利用できない場合のみ
- iOS:利用可能な場合は、ベンダー用識別子(IDFV)および広告主用識別子(IDFA)
デバイスパラメータ:ロケール、Device Make、Device Model、Build Version(モバイルプラットフォームで必要
以下のコード例では、各プラットフォームと識別子の種類に応じた検索方法を示しています。
サンプル・アプリケーション
リファレンス実装
iOS と Android 用の完全な動作例で、デバイス・データの取得パターンを示します。
iOSデバイス識別子
iOSデバイスは、正確なアトリビューションのために、IDFV(常時)とIDFA(ユーザーがトラッキング許可を与えた場合)、さらにATT認可ステータスが必要です。
必要なiOS識別子
識別子の要件
- IDFV:トラッキング許可に関わらず、全てのS2Sリクエストに必要。
- IDFA:ユーザーがApp Tracking Transparencyに同意した場合、提供されるべきである。
- ATTステータス:全てのリクエストに必要な認証ステータスコード(0-3)
実装ガイド
広告主用識別子(IDFA)
広告主向け識別子(IDFA)により、広告主はユーザーのアクション(広告のクリック、アプリのインストール)を追跡して特定のキャンペーンに帰属させ、正確なターゲティングと最適化を行うことができます。
iOS 14.5以降、アプリがIDFAにアクセスする前に、ユーザーはApp Tracking Transparency(ATT)フレームワークを介してオプトインする必要があります。ユーザーの同意がない場合、IDFAはすべてのゼロを返し、トラッキング機能を制限します。
ベンダー用識別子(IDFV)
Identifier for Vendors (IDFV)は、Appleがデバイスに割り当てる、ベンダー/デベロッパー固有の一意の識別子です。デバイス上の同じベンダーのすべてのアプリで一貫性が保たれるため、個人を特定することなく、アプリを横断した行動追跡が可能になります。
実施手順
- IDFA アクセスを試みる前に ATT プロンプトが表示され、処理されることを確認する。
- IDFAを取得し(許可されている場合)、APIリクエストのためにサーバーに渡す。
- IDFVを取得し、APIリクエスト用にサーバーに渡す(常に必要
- すべてのリクエストにATT認証ステータスを含める
コード例
ATT認可の要求とIDFA/IDFVの取得
#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];
import AdSupport
import AppTrackingTransparency
import UIKit
func retrieveIdentifiers() {
// Request ATT authorization (iOS 14.5+)
ATTrackingManager.requestTrackingAuthorization { status in
DispatchQueue.main.async {
switch status {
case .authorized:
// ATT authorized, retrieve IDFA
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
print("IDFA: \(idfa)")
print("ATT Status: \(status.rawValue)") // Status = 3
case .denied:
print("ATT Status: Denied (\(status.rawValue))") // Status = 2
case .restricted:
print("ATT Status: Restricted (\(status.rawValue))") // Status = 1
case .notDetermined:
print("ATT Status: Not Determined (\(status.rawValue))") // Status = 0
@unknown default:
print("Unknown ATT status.")
}
// Retrieve IDFV (always available)
if let idfv = UIDevice.current.identifierForVendor?.uuidString {
print("IDFV: \(idfv)")
} else {
print("Unable to retrieve IDFV.")
}
}
}
}
// Call the function to retrieve identifiers
retrieveIdentifiers()
識別子の有効性
- IDFA:iOS 14.5+からのATT認可が必要。同意がない場合は、すべてのゼロを返します。
- IDFV:常に利用可能-すべてのSingular APIリクエストに含める
- ATTステータス値:0=Undetermined, 1=Restricted, 2=Denied, 3=Authorized
Androidデバイス識別子(Google Play)
Google Playサービスを利用するAndroidデバイスは、すべてのリクエストでアプリセットID(ASID)を必要とし、利用可能な場合はGoogle Advertising ID(GAID/AIFA)を必要とします。
必要なGoogle Play識別子
識別子の要件
- ASID:Google Play端末のすべてのS2Sリクエストに必要です。
- AIFA/GAID:利用可能な場合は提供されるべきである(オプトアウト不可
実装ガイド
グーグル広告識別子(GAID)
AIFA または Android Advertising ID (AAID) としても知られる Google Advertising Identifier (GAID) は、Android 端末に割り当てられた一意のユーザーリセット可能な識別子です。 広告主や開発者は、プライバシーを維持しながら、キャンペーンのターゲティングと最適化のために、アプリ全体でユーザーの行動を追跡し、属性化することができます。
依存関係
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);
}
}
});
}
}
依存関係
dependencies {
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
}
パーミッション
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
使用方法
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch {
val googleAdId = AdIdUtils.getGoogleAdId(applicationContext)
Log.d("MainActivity", "Retrieved Google Ad ID: $googleAdId")
}
}
}
実装
import android.content.Context
import android.util.Log
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
object AdIdUtils {
suspend fun getGoogleAdId(context: Context): String? {
return withContext(Dispatchers.IO) {
try {
val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
val adId = adInfo.id
val isLimitAdTrackingEnabled = adInfo.isLimitAdTrackingEnabled
Log.d("GoogleAdID", "Advertising ID: $adId")
Log.d("GoogleAdID", "Limit Ad Tracking: $isLimitAdTrackingEnabled")
adId
} catch (e: Exception) {
Log.e("GoogleAdID", "Error retrieving GAID", e)
null
}
}
}
}
アプリセットID (ASID)
Android App Set IDは、同じ開発者のためにプライバシーに配慮したクロスアプリ・トラッキングを提供します。 分析や不正防止に役立ちますが、パーソナライズされた広告には使用できません。
依存関係
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);
});
}
}
依存関係
dependencies {
implementation 'com.google.android.gms:play-services-appset:16.1.0'
}
使用方法
AppSetIdUtils.getAppSetId(applicationContext)
実装
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
object AppSetIdUtils {
fun getAppSetId(context: Context) {
val client: AppSetIdClient = AppSet.getClient(context)
val task = client.appSetIdInfo
task.addOnSuccessListener { info -
val appSetId: String = info.id
val scope: Int = info.scope
Log.d("AppSetID", "App Set ID: $appSetId")
Log.d("AppSetID", "Scope: ${if (scope == AppSetIdInfo.SCOPE_DEVELOPER) "Developer" else "App"}")
}.addOnFailureListener { exception -
Log.e("AppSetID", "Failed to retrieve App Set ID", exception)
}
}
}
Android 端末の識別子(Google Play 以外)
Google Playサービスを利用していないAndroid端末では、端末の製造元や配布方法に応じて、別の識別子が必要となります。
Amazonデバイス識別子
AMID:Google Playサービスを利用していないAmazon Fire端末の場合、Amazon Advertising IDを提供する必要があります。
アマゾンID (AMID)
Amazon Advertising Identifierは、Google Play Servicesを利用しないAmazon Fireデバイスにおいて、ユーザーのプライバシーを維持しながらアトリビューションを可能にする、ユーザーリセット可能な広告トラッキングを可能にします。
要件
- Fire OS 5.1+を実行しているAmazon Fireデバイスで動作します。
- ユーザーの広告トラッキングの制限設定を尊重します。
- Fire OS非搭載端末ではご利用いただけない場合があります。
使用方法
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);
}
}
}
利用方法
AdvertisingIdHelper.getAmazonAdvertisingId(contentResolver)
実装
import android.content.ContentResolver
import android.provider.Settings
import android.util.Log
object AdvertisingIdHelper {
fun getAmazonAdvertisingId(contentResolver: ContentResolver) {
try {
val limitAdTracking = Settings.Secure.getInt(contentResolver, "limit_ad_tracking") != 0
val advertisingID = Settings.Secure.getString(contentResolver, "advertising_id")
Log.d("AdvertisingID", "Amazon Advertising ID: $advertisingID")
Log.d("LimitAdTracking", "Limit Ad Tracking: $limitAdTracking")
} catch (e: Settings.SettingNotFoundException) {
Log.e("AdvertisingID", "Advertising ID not supported on this device", e)
}
}
}
中国OEM識別子
OAID:Google Playサービスを利用していない中国製端末には、Open Advertising IDを提供する必要があります。
オープン広告 ID (OAID)
オープン広告識別子(OAID)は、中国で製造されたAndroidデバイス上の広告のためのユニークな匿名識別子です。Mobile Security Alliance (MSA)により、Google Playサービスが利用できない端末のGAIDの代替として導入されました。
対応デバイスHuawei、Xiaomi、OPPO、Vivo、その他の中国製Androidデバイス
MSA SDKまたはHuawei Mobile Services(HMS)経由でアクセス。
依存関係
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);
}
}
}
依存関係
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
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "OAIDExample"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getOAID()
}
private fun getOAID() {
try {
val deviceId = DeviceId(this)
deviceId.getDeviceIds(object : IIdentifierListener {
override fun onSupport(isSupport: Boolean, supplier: DeviceIdSupplier?) {
if (isSupport && supplier != null) {
val oaid = supplier.oAID
Log.d(TAG, "OAID: $oaid")
} else {
Log.e(TAG, "OAID not supported on this device")
}
}
})
} catch (e: Exception) {
Log.e(TAG, "Error retrieving OAID", e)
}
}
}
Android IDフォールバック
ANDIの制限:Android IDは、他の識別子が利用できない場合、およびGoogle Playストア経由でアプリが配布されていない場合にのみ提供することができます。 Google Playアプリでは禁止されています。
Android ID (ANDI)
Android IDは、デバイスの最初のセットアップ時に生成される一意の64ビット識別子です。 Android 8.0 (Oreo)から、アプリごと、ユーザーごとにスコープされるようになり、同じ署名キーを共有しない限り、異なるアプリは異なるAndroid IDを受け取ります。
永続性:デバイスのファクトリーリセットや、OTAアップデート後のアプリのアンインストール/再インストールがない限り、一定に保たれます。
import android.provider.Settings;
import android.content.Context;
String androidId = Settings.Secure.getString(
context.getContentResolver(),
Settings.Secure.ANDROID_ID
);
import android.provider.Settings
val androidId: String = Settings.Secure.getString(
contentResolver,
Settings.Secure.ANDROID_ID
)
ウェブとクロスプラットフォームの識別子
ウェブアプリケーションとクロスプラットフォームの実装では、正確なアトリビューション追跡のためにSingular Device ID(SDID)が必要です。
必要なウェブ識別子
SDID:ウェブ、PC、コンソール、およびCTVプラットフォームのすべてのS2Sリクエストに必要なSingular Device ID。
SingularウェブSDKデバイスID
Singular Device 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()をコールしてください。初期化前に取得しようとすると null が返されます。
モバイルデバイスパラメータ
必要なデバイスパラメータは、モバイルプラットフォームでのアトリビューションとアナリティクスに不可欠なコンテキストを提供します。
必須パラメータ
モバイルプラットフォームLocale、Device Make、Device Model、Buildは、iOSとAndroidの全てのS2Sリクエストに必要です。
パラメータ取得
デバイスの完全なプロファイリングのために、ロケール、メーカー、モデル、ビルド情報を収集します。
#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;
}
}
import Foundation
import UIKit
// Retrieve Locale
func retrieveLocale() - String {
let locale = Locale.current.identifier
print("Locale: \(locale)")
return locale
}
// Retrieve Manufacturer (always Apple for iOS)
func retrieveManufacturer() - String {
return "Apple"
}
// Retrieve Device Model
func deviceModel() - String? {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
print("Device Model: \(identifier)")
return identifier
}
// Retrieve Build Version
func buildVersion() - String? {
var size: Int = 0
sysctlbyname("kern.osversion", nil, &size, nil, 0)
var build = [CChar](repeating: 0, count: size)
sysctlbyname("kern.osversion", &build, &size, nil, 0)
let buildVersion = String(cString: build)
print("Build Version: \(buildVersion)")
return buildVersion
}
import android.os.Build;
import java.util.Locale;
// Locale (lc parameter)
String locale = Locale.getDefault().toString();
// Device Make (ma parameter)
String deviceMake = Build.MANUFACTURER;
// Device Model (mo parameter)
String deviceModel = Build.MODEL;
// Build (bd parameter)
String build = "Build/" + Build.ID;
import android.os.Build
import java.util.Locale
// Locale (lc parameter)
val locale: String = Locale.getDefault().toString()
// Device Make (ma parameter)
val deviceMake: String = Build.MANUFACTURER
// Device Model (mo parameter)
val deviceModel: String = Build.MODEL
// Build (bd parameter)
val build: String = "Build/" + Build.ID
パラメータのマッピング
- ロケール(lc):言語と地域コード(例:en_US、zh_CN
- メーカー(ma):デバイスメーカー(アップル、サムスン、シャオミ
- モデル(mo):特定のデバイスモデル(iPhone14,2、SM-G991B
- ビルド(bd):OSのビルドバージョンの先頭に "Build/"を付けたもの。