pp_asa_attribution

Apple search ads attribution plugin

Built on

  • Flutter 3.24.5+
  • iOS 14.3+
  • Swift 5.0+

Requirements

  • Add iOS Framework: iAd、AdServices、AdSupport、AppTrackingTransparency

Apple Documents

Docs API

developer.apple.com/documentation/adservices/aaattribution

developer.apple.com/documentation/adservices/changelog

Roles

The token that the framework returns is a Base64 encoded string and has a 24-hour TTL. You can provide the token to a Mobile Measurement Provider ( MMP), or app developers can use it to make a POST API call to fetch attribution records within the 24-hour TTL window. Use a single token in the request body and use a content-type of text/plain in the header, as the following example shows:

POST https://api-adservices.apple.com/api/v1/
--header 'Content-Type: text/plain' \
--data-raw


G9i5hC8lQJeGOfmS+MFycll/025oJEjtpZ+rs4AUkDEJh52fT8RrjwIR/ h+2JOpXz4MRdmtcemL8WTTHfNN52tjqjbWupke40AAAAVADAAAAvQAAAIAg QF1+XF4Tl2IZ7Bw/M6ufUHt+UcIhuBeJT8YenB2v36bnZKEjvq/ IH8rqXkRELTHdyiqOYtpy837+UjF/NjE6t1/ l7sIn71b0t3FEXJd8QOtl3Bi6iQyJgGeN8w8X0MK1PDqz9nLJtRD/ wl+p112qR2YrMDyyKnwNrbfRhnGB9AAAAB7wAXlwNHelWf5RT2bzSJcGflq ELMCGoDEHIl7jF6kAAACfAb9ylY8ffdbTlyJODQYQ/ 6V9qbaBAAAAhgUBW39MQI1A0SZgNmZFz4KPaF94BxBzd4rDkjr/ eSeuaXWCmEW3ZhBzE/MOM17hAPBVlDhTPcZ/2ybr3WYIkfb+AAg/ 7jxGpDXgTtco3fzTytnZpEaI5SenXHALIexQAUTBsfBW2HCMQuTRo+7anoW kf69656ZAWcSc3DEQ1CAkUSKO9X7iAAABBEQQBQA=

Important

Important !!!

A 404 response can occur if you make an API call too quickly after receiving a valid token. A best practice is to initiate retries > at intervals of 5 seconds, with a maximum of three attempts.

Getting Started

Future<void> fetchASAData1() async {
    Map<String, dynamic>? attributionJson =
        await PPAsaAttribution().requestAttributionDetails();
    int retryCount = 0;
    while (attributionJson == null && retryCount < 3) {
      print('uploadASAData attributionJson is null, retry count: $retryCount');
      // 延迟5秒后重试
      await Future.delayed(const Duration(seconds: 5));
      attributionJson = await PPAsaAttribution().requestAttributionDetails();
      retryCount++;
    }
    if (attributionJson == null) {
      print('uploadASAData json null after 3 retries');
      return;
    }
    print('uploadASAData attributionJson: $attributionJson');
  }

  Future<void> fetchASAData2() async {
    String? token = await PPAsaAttribution().attributionToken();
    if (token == null) {
      print('uploadASAData token is null');
      return;
    }
    print('uploadASAData token: $token');
    // 延迟500毫秒后再请求
    await Future.delayed(const Duration(milliseconds: 500));
    Map<String, dynamic>? attributionJson =
        await PPAsaAttribution().requestAttributionWithToken(token);
    int retryCount = 0;
    while (attributionJson == null && retryCount < 3) {
      print('uploadASAData attributionJson is null, retry count: $retryCount');
      // 延迟5秒后重试
      await Future.delayed(const Duration(seconds: 5));
      attributionJson =
          await PPAsaAttribution().requestAttributionWithToken(token);
      retryCount++;
    }
    if (attributionJson == null) {
      print('uploadASAData json null after 3 retries');
      return;
    }
    print('uploadASAData attributionJson: $attributionJson');
  }

Results

{
    clickDate: 2025-03-15T12:04Z, 
    countryOrRegion: US, 
    campaignId: 1234567890, 
    conversionType: Download, 
    keywordId: 12323222, 
    adGroupId: 1234567890, 
    attribution: true, 
    claimType: Click, 
    orgId: 1234567890, 
    adId: 1234567890
}