Retrieving Device Data Guide
Singular requires specific device identifiers to be included in all API requests for accurate attribution. These identifiers include:
- Google Advertising ID (GAID) and Google App Set ID (ASID) for Google Play Devices
- Amazon Advertising ID for Non-Google Play Amazon Devices
- Open Advertising ID (OAID) for Chinese-manufactured Android devices
- And if none of the above are available, the Android ID (ANDI) for Non-Google Play Devices
- Identifier for Advertisers (IDFA) and Identifier for Vendors (IDFV) for iOS Devices
Singular also requires some Mobile device Parameters:
- Locale (e.g., en_US)
- Device Make (e.g., Samsung)
- Device Model (e.g., iPhone 12, Samsung Galaxy S21)
- Build (e.g., Build/13D15)
Singular provides code snippet examples to help you obtain these identifiers, which can be found below.
Sample Device Info Class
Identifiers
Required iOS Identifiers
- The IDFV is required on all S2S requests
- The IDFA should be provided if App Tracking Transparency Consent was provided by the user.
- The ATT Authorization Status is also required.
Retrieving the Identifier for Advertisers (IDFA)
The Identifier for Advertisers (IDFA) helps advertisers track and attribute user actions (e.g., ad clicks, app installs) to specific campaigns, enabling precise ad targeting and campaign optimization.
Starting with iOS 14.5, users must opt-in via the App Tracking Transparency (ATT) framework before apps can access their IDFA. If users do not opt-in, the IDFA is unavailable, limiting tracking capabilities.
Retrieving the Identifier for Vendors (IDFV)
The Identifier for Vendors (IDFV) is a unique identifier assigned by Apple to a device, which is specific to a particular vendor or developer. It remains consistent across all apps from the same vendor on a given device, allowing the vendor to track user behavior and interactions across their app ecosystem without identifying the user personally.
- Ensure the ATT prompt is shown and handled before attempting to access the IDFA.
- If you are using ATT, capture the IDFA and pass it back to your server for use on Singular API requests.
- Capture the IDFV and pass it back to your server for use on Singular API requests.
Example: Requesting ATT Authorization Status to Retrieve IDFA and IDFV with Console Logs
Here is the Objective-C and Swift code snippets to retrieve both the IDFA (Identifier for Advertisers) and IDFV (Identifier for Vendor) with console logs. This code includes handling App Tracking Transparency (ATT) permissions, which are required to access the IDFA starting from iOS 14.5.
#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]);
break;
}
case ATTrackingManagerAuthorizationStatusDenied:
case ATTrackingManagerAuthorizationStatusRestricted:
case ATTrackingManagerAuthorizationStatusNotDetermined:
// ATT not authorized or not determined
NSLog(@"Tracking not authorized or not determined.");
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)")
case .denied, .restricted, .notDetermined:
// ATT not authorized or not determined
print("Tracking not authorized or not determined.")
@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: Requires ATT authorization from iOS 14.5+. Without user consent, the IDFA will return all zeros.
- IDFV: Always available and should should always be provided on Singular API Requests.
Required Android Identifiers (Google Play Devices)
- The ASID is required on all S2S requests
- The AIFA (GAID) should be provided if available.
Retrieving the Google Advertising Identifier (GAID)
The Google Advertising Identifier (GAID), also known as AIFA in Singular or Android Advertising ID (AAID), is a unique, user-resettable identifier assigned to Android devices. It helps advertisers and app developers track and attribute user actions (e.g., ad clicks, app installs) across apps to specific campaigns, enabling precise ad targeting and campaign optimization, while maintaining user privacy.
Make sure you have added the required dependency for Google Play Services in your build.gradle file:
dependencies {
implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
}
If your app build is targeting Android 12/API level 31 or higher, add permissions in the AndroidManifest.xml to access the Google Advertising ID:
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
To use this method, simply call it from your activity or application class:
AdIdUtils.getGoogleAdId(getApplicationContext());
Java Code to Retrieve Google Advertising ID (GAID)
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 {
// Method to retrieve the Google Advertising ID (GAID)
public static void getGoogleAdId(Context context) {
// Running the task in a background thread
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
// Retrieve the Advertising ID info
Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
// Get the GAID (Google Advertising ID)
String adId = adInfo.getId();
// Check if "Limit Ad Tracking" is enabled by the user
boolean isLimitAdTrackingEnabled = adInfo.isLimitAdTrackingEnabled();
// Log the results
Log.d("GoogleAdID", "Advertising ID: " + adId);
Log.d("GoogleAdID", "Limit Ad Tracking Enabled: " + isLimitAdTrackingEnabled);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
Make sure you have added the required dependency for Google Play Services in your build.gradle file:
dependencies {
implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
}
If your app build is targeting Android 12/API level 31 or higher, add permissions in the AndroidManifest.xml to access the Google Advertising ID:
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
Usage
To use this function, you need to call it from a coroutine scope, such as within a ViewModel or an activity using lifecycleScope. Here’s an example of how you might call it in an activity:
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Launch a coroutine to fetch the Google Ad ID
lifecycleScope.launch {
val googleAdId = AdIdUtils.getGoogleAdId(applicationContext)
Log.d("MainActivity", "Retrieved Google Ad ID: $googleAdId")
}
}
}
Java Code to Retrieve Google Advertising ID (GAID)
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 {
// Function to retrieve Google Advertising ID (GAID) using coroutines
suspend fun getGoogleAdId(context: Context): String? {
return withContext(Dispatchers.IO) {
try {
// Retrieve the Advertising ID info
val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
// Get the GAID (Google Advertising ID)
val adId = adInfo.id
// Check if "Limit Ad Tracking" is enabled by the user
val isLimitAdTrackingEnabled = adInfo.isLimitAdTrackingEnabled
// Log the results
Log.d("GoogleAdID", "Advertising ID: $adId")
Log.d("GoogleAdID", "Limit Ad Tracking Enabled: $isLimitAdTrackingEnabled")
adId
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}
}
Retrieving the App Set ID (ASID)
The Android App Set ID provides a way for developers to track users across their own apps in a privacy-conscious manner. It is particularly useful for analytics and fraud prevention but cannot be used for advertising purposes such as personalized ads or measurement.
Make sure you have added the required dependency for Google Play Services in your build.gradle file:
dependencies {
implementation 'com.google.android.gms:play-services-appset:16.1.0'
}
Usage
To use this function, simply call it from your activity or application class:
AppSetIdUtils.getAppSetId(getApplicationContext());
Java Code to Retrieve App Set ID
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.OnSuccessListener;
import com.google.android.gms.tasks.Task;
public class AppSetIdUtils {
// Method to retrieve the App Set ID
public static void getAppSetId(Context context) {
// Get the AppSetIdClient instance
AppSetIdClient client = AppSet.getClient(context);
// Retrieve the App Set ID information asynchronously
Task<AppSetIdInfo> task = client.getAppSetIdInfo();
task.addOnSuccessListener(new OnSuccessListener<AppSetIdInfo>() {
@Override
public void onSuccess(AppSetIdInfo info) {
// Get the App Set ID and its scope
String appSetId = info.getId();
int scope = info.getScope();
// Log the results
Log.d("AppSetID", "App Set ID: " + appSetId);
Log.d("AppSetID", "Scope: " + (scope == AppSetIdInfo.SCOPE_DEVELOPER ? "Developer" : "App"));
}
}).addOnFailureListener(e -> {
// Handle any errors that occur during retrieval
Log.e("AppSetID", "Failed to retrieve App Set ID", e);
});
}
}
Ensure you have added the necessary dependency for Google Play services in your build.gradle file:
dependencies {
implementation 'com.google.android.gms:play-services-appset:16.1.0'
}
Usage
To use this function, simply call it from your activity or application class:
AppSetIdUtils.getAppSetId(applicationContext)
Kotlin Code to Retrieve App Set ID
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.tasks.Task
object AppSetIdUtils {
// Function to retrieve the App Set ID
fun getAppSetId(context: Context) {
// Get the AppSetIdClient instance
val client: AppSetIdClient = AppSet.getClient(context)
// Retrieve the App Set ID information asynchronously
val task: Task<AppSetIdInfo> = client.appSetIdInfo
task.addOnSuccessListener { info ->
// Get the App Set ID and its scope
val appSetId: String = info.id
val scope: Int = info.scope
// Log the results
Log.d("AppSetID", "App Set ID: $appSetId")
Log.d("AppSetID", "Scope: ${if (scope == AppSetIdInfo.SCOPE_DEVELOPER) "Developer" else "App"}")
}.addOnFailureListener { exception ->
// Handle any errors that occur during retrieval
Log.e("AppSetID", "Failed to retrieve App Set ID", exception)
}
}
}
Required Android Identifiers (Non-Google Play Devices)
If no ASID or AIFA are available:
- The AMID (Amazon Identifier) should be provided. Amazon Devices Only.
Retrieving the Amazon ID (AMID)
To capture the Amazon Advertising Identifier in your Android app, you can use the Settings.Secure class to retrieve the identifier and check the user's ad tracking preferences. Here's a clean and simple code example based on the information provided by Amazon's documentation:
Make sure to handle scenarios where the Advertising ID might not be available (e.g., on non-Fire OS devices or older versions of Fire OS).
Always respect the user's Limit Ad Tracking preference when using this identifier for advertising or analytics purposes. This code should work on Amazon Fire devices running Fire OS 5.1 or later, as per Amazon's guidelines
You can call this method from your activity or service by passing in the ContentResolver:
// Example usage in an Activity
AdvertisingIdHelper.getAmazonAdvertisingId(getContentResolver());
Java Code to Retrieve the Amazon Advertising ID (AMID)
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 {
// Get user's ad tracking preference
limitAdTracking = (Settings.Secure.getInt(contentResolver, "limit_ad_tracking") == 0) ? false : true;
// Get the Amazon Advertising ID
advertisingID = Settings.Secure.getString(contentResolver, "advertising_id");
// Log the values for demonstration purposes
Log.d("AdvertisingID", "Amazon Advertising ID: " + advertisingID);
Log.d("LimitAdTracking", "Limit Ad Tracking: " + limitAdTracking);
} catch (SettingNotFoundException e) {
// Handle case where settings are not available (e.g., non-Fire OS devices)
Log.e("AdvertisingID", "Advertising ID not supported on this device", e);
}
}
}
You can call this method from an Activity or Service by passing in the ContentResolver:
// Example usage in an Activity
AdvertisingIdHelper.getAmazonAdvertisingId(contentResolver)
Kotlin Code to Retrieve the Amazon Advertising ID (AMID)
import android.content.ContentResolver
import android.provider.Settings
import android.util.Log
object AdvertisingIdHelper {
fun getAmazonAdvertisingId(contentResolver: ContentResolver) {
try {
// Get user's ad tracking preference
val limitAdTracking = Settings.Secure.getInt(contentResolver, "limit_ad_tracking") != 0
// Get the Amazon Advertising ID
val advertisingID = Settings.Secure.getString(contentResolver, "advertising_id")
// Log the values for demonstration purposes
Log.d("AdvertisingID", "Amazon Advertising ID: $advertisingID")
Log.d("LimitAdTracking", "Limit Ad Tracking: $limitAdTracking")
} catch (e: Settings.SettingNotFoundException) {
// Handle case where settings are not available (e.g., non-Fire OS devices)
Log.e("AdvertisingID", "Advertising ID not supported on this device", e)
}
}
}
- The OAID (Open Advertising Identifier) should be provided. China domestic devices.
Retrieving the Open Advertising ID (OAID)
The Open Advertising Identifier (OAID) is a unique, anonymous identifier used for advertising purposes on Android devices, particularly those manufactured in China. It was introduced by the Mobile Security Alliance (MSA) as an alternative to Google's Advertising ID (GAID) for devices where Google Play Services are unavailable or not supported, such as in the Chinese market.
The OAID is primarily used for advertising attribution and user tracking in environments where Google Play Services are restricted, allowing advertisers and developers to track user behavior while maintaining anonymity.
OAID is available on most Chinese-manufactured Android devices, including those from brands like Huawei, Xiaomi, and others. It can be accessed using the MSA SDK or Huawei Mobile Services (HMS).
Ensure your build.gradle file includes the necessary dependencies for the MSA SDK.
dependencies {
implementation 'com.bun.msa.sdk:msa:1.0.26' // Example version; check for the latest one
}
Java Code to Retrieve OAID
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);
// Initialize and request OAID
getOAID();
}
private void getOAID() {
try {
// Create a DeviceId instance and request OAID asynchronously
DeviceId deviceId = new DeviceId(this);
deviceId.getDeviceIds(new IIdentifierListener() {
@Override
public void onSupport(boolean isSupport, DeviceIdSupplier supplier) {
if (isSupport && supplier != null) {
// Retrieve OAID from supplier
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);
}
}
}
Add the MSA SDK to your project: Similar to the Java version, you need to integrate the MSA SDK into your project. Ensure you have the correct dependency in your build.gradle file:
dependencies {
implementation 'com.bun.msa.sdk:msa:1.0.26' // Example version; check for the latest one
}
Kotlin Code to Retrieve OAID
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)
// Initialize and request OAID
getOAID()
}
private fun getOAID() {
try {
val deviceId = DeviceId(this)
deviceId.getDeviceIds(object : IIdentifierListener {
override fun onSupport(isSupport: Boolean, supplier: DeviceIdSupplier?) {
if (isSupport && supplier != null) {
// Retrieve OAID from supplier
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)
}
}
}
- If no other device identifier exists, then you may provide the ANDI (Android ID).
Retrieving the Android ID (ANDI)
The Android ID is a unique 64-bit identifier generated by the Android operating system when a device is first set up. It is designed to be persistent across the lifetime of the device, but it can be reset under certain conditions such as a factory reset.
The Android ID is unique to each device and, starting from Android 8.0 (Oreo), it is scoped per app and per user. This means that different apps on the same device will receive different Android IDs unless they share the same signing key.
The Android ID remains constant unless the device undergoes a factory reset or if an app is uninstalled and reinstalled after an OTA (over-the-air) update.
To retrieve the Android ID in an Android app, you can use the following code snippet:
import android.provider.Settings;
import android.content.Context;
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
You can call this method from an Activity or Service by passing in the ContentResolver:
import android.os.Bundle
import android.provider.Settings
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Find the TextView in the layout to display the Android ID
val textView: TextView = findViewById(R.id.textView)
// Retrieve the Android ID
val androidId: String = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
}
}
Required Web Identifiers
- The SDID is required on all S2S requests
Retrieving the Singular Web SDK Device ID (SDID)
Description
You must have the Singular Web SDK implemented.
UsageTo use this method, simply call it from your web site code after the Singular SDK has Initialized:
window.singularSdk.getSingularDeviceId()
Required Mobile Device Params
- The Locale, Device Make, Device Model, and Build are required on all S2S requests
Retrieving Locale, Device Make, Model, and Build
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <sys/sysctl.h>
// Retrieve the Locale
NSString *retrieveLocale() {
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(@"Locale: %@", locale);
return locale;
}
// Retrieve the Manufacturer
NSString *retrieveManufacturer() {
// Set the Device Make to Apple
return @"Apple";
}
// Retrieve the 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 the 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;
}
}
// Example usage
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Retrieve Locale
NSString *locale = retrieveLocale();
// Retrieve Device Make
NSString *make = retrieveManufacturer();
// Retrieve Device Model
NSString *model = deviceModel();
// Retrieve Build Version
NSString *build = buildVersion();
// Log results
if (locale) {
NSLog(@"Locale: %@", locale);
}
if (make) {
NSLog(@"Device Make: %@", make);
}
if (model) {
NSLog(@"Device Model: %@", model);
}
if (build) {
NSLog(@"Build Version: %@", build);
}
}
return 0;
}
import Foundation
// Retrieve the Locale
func retrieveLocale() -> String {
let locale = Locale.current.identifier
print("Locale: \(locale)")
return locale
}
// Retrieve the Device Model
import UIKit
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 the 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
}
// Example usage:
let locale = retrieveLocale()
print("Locale: \(locale)")
let deviceMake = "Apple"
print("Device Make: \(deviceMake)")
if let model = deviceModel() {
print("Device Model: \(model)")
}
if let build = buildVersion() {
print("Build Version: \(build)")
}
// Locale - lc= query parameter
String locale = Locale.getDefault().toString(); // Converts Locale object to string
// Make - ma= query parameter
String deviceMake = Build.MANUFACTURER; // Gets the device manufacturer name
// Model - mo= query parameter
String deviceModel = Build.MODEL; // Gets the device model
// Build - bd= query parameter
String build = "Build/" + Build.ID; // Gets the build ID and appends it to "Build/"
// Locale - lc= query parameter
val locale: String = Locale.getDefault().toString() // Converts Locale object to string
// Make - ma= query parameter
val deviceMake: String = Build.MANUFACTURER // Gets the device manufacturer name
// Model - mo= query parameter
val deviceModel: String = Build.MODEL // Gets the device model
// Build - bd= query parameter
val build: String = "Build/" + Build.ID // Gets the build ID and appends it to "Build/"