Skip to main content
Solved

Does Apple Search Ads attribution appear in webhook payloads / Customer API attributes (subscriber_attributes)?

  • May 29, 2026
  • 2 replies
  • 19 views

Forum|alt.badge.img

Hi, we are setting up server-side analytics forwarding and I need to confirm where Apple Search Ads (ASA) attribution is stored after RevenueCat collects it.

Context

- Our iOS app calls `Purchases.enableAdServicesAttributionTokenCollection()`, so RevenueCat collects the AdServices attribution token.
- On our backend we receive RevenueCat webhooks and forward the event payload to our analytics tool. We'd like to rely on the webhook `event.subscriber_attributes` map for per-customer context (we also read the Customer API `attributes`).

 

 

What I can't find in the docs

1. When RevenueCat exchanges the AdServices token, where does the resulting ASA attribution (campaign ID / ad group ID / keyword ID / org ID) get stored on the customer? Is it stored as reserved subscriber attributes? If so, what are the exact attribute names (e.g. `$apple_search_ads_*` or similar)?
2. Does this ASA attribution data appear in the **webhook event payload** under `subscriber_attributes`? Or is it only available via Charts and specific built-in integrations (not webhooks / not the Customer API attributes list)?
3. If it's not in webhooks, what's the recommended way to read per-customer ASA attribution programmatically (Customer API `attributes` expand? Scheduled Data Exports?)?

The docs list "Apple search ads campaign / ad group / keyword" as Chart filters and say attribution is "available via Charts and other integrations," but I can't find confirmation that these land in `subscriber_attributes` (and therefore in webhooks or the Customer API attributes list).

For reference, the reserved attributes I currently see on customers include names like `$appsflyerId`, `$tenjinId`, `$idfa`, `$idfv`, `$ip`, `$attConsentStatus` — but no ASA-related attribute appears (note: we haven't shipped token collection to a public build yet, so that may be expected).

Thanks!

Best answer by chris_perriam

Hi ​@chuck-2b8203, great questions! let me answer each one with what RevenueCat actually does on the backend after the SDK sends us the AdServices token.

1. Where ASA attribution is stored after RevenueCat collects the AdServices token

When Purchases.enableAdServicesAttributionTokenCollection() is called and we receive the token, we exchange it with Apple's AdServices endpoint and store the raw fields (orgIdcampaignIdadGroupIdkeywordIdadIdclaimTypeconversionTypecountryOrRegionclickDateimpressionDate) in an internal attribution table.

What lands on the customer object as reserved subscriber attributes depends on whether you have an Advanced Apple Ads integration set up (the one where you Sign in with Apple / authorize the Apple Search Ads Campaign Management API). The Advanced integration is what lets us resolve campaignId → campaignNameadGroupId → adGroupNamekeywordId → keyword text. That resolution job then writes the following reserved attributes:

Attribute Value

$mediaSource

"Apple Search Ads"

$campaign

Campaign name

$adGroup

Ad group name

$keyword

Keyword text (only when search match is disabled, since Apple doesn't return a keywordId for search-match-on traffic)

These match the same $mediaSource / $campaign / $adGroup / $keyword keys which can be used for AppsFlyer, Adjust, Branch, Tenjin, etc. They're documented in Customer Attributes → Attribution Data.

A few important caveats:

  • No Apple Ads integration, or only Basic: the AdServices token is collected and stored, and your Charts will still get the install/attribution signal, but no $mediaSource / $campaign / $adGroup / $keyword reserved attributes are written to the customer. Resolving names requires the Advanced integration's auth token.
  • Organic installs (Apple returns attribution: false) don't get any of these attributes set.
  • The $apple_search_ads_* style key shape you guessed at doesn't exist

2. Does this show up in webhook event.subscriber_attributes?

Yes. Once those reserved attributes are written, they're in the same subscriber_attributes map you already see on webhook events (alongside $idfa$idfv$ip$attConsentStatus, etc.). So on a webhook for a customer attributed to ASA via the Advanced integration, you should see entries like:

"subscriber_attributes": {

"$mediaSource": { "value": "Apple Search Ads", "updated_at_ms": ... },

"$campaign": { "value": "<Campaign Name>", "updated_at_ms": ... },

"$adGroup": { "value": "<Ad Group Name>", "updated_at_ms": ... },

"$keyword": { "value": "<Keyword>", "updated_at_ms": ... }

}

A couple of practical timing notes:

  • The AdServices → Apple Ads resolution runs asynchronously after we receive the token. Apple itself recommends allowing up to ~24h for attribution to be available, and we recommend allowing up to 7 days for full coverage. So a INITIAL_PURCHASE webhook fired immediately after install can land before these attributes are written. They'll be present on later events for the same subscriber.
  • The reason you don't see ASA attributes on your current customers is likely what you suspected: token collection isn't shipped to a public build yet, and TestFlight/sandbox usually returns placeholder values that we filter out.

3. Reading per-customer ASA attribution programmatically

You have three options that all read the same underlying reserved attributes:

  • Webhooks — event.subscriber_attributes as above. This is what we generally recommend for forwarding to your analytics.
  • Customer API v2 — GET /v2/projects/{project_id}/customers/{customer_id}/attributes returns the full attribute list, including the $mediaSource / $campaign / $adGroup / $keyword entries when set (API reference). The v1 /subscribers/{app_user_id} response also exposes them under subscriber.subscriber_attributes.
  • Scheduled Data Exports — the customer-level attribute fields (media_sourcecampaignad_groupkeyword) are exported per-row, so this is the easiest path if you're doing offline analysis or backfilling.

So the short version: set up the Advanced Apple Ads integration, ship token collection to a public build, and you'll see ASA attribution land in subscriber_attributes (and therefore in webhooks and the Customer API attributes list) under the standard reserved keys. Without the Advanced integration, ASA only powers Charts and Apple-Ads-specific destinations, not the per-customer attribute map.

Hope that helps!

2 replies

chris_perriam
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • Answer
  • May 30, 2026

Hi ​@chuck-2b8203, great questions! let me answer each one with what RevenueCat actually does on the backend after the SDK sends us the AdServices token.

1. Where ASA attribution is stored after RevenueCat collects the AdServices token

When Purchases.enableAdServicesAttributionTokenCollection() is called and we receive the token, we exchange it with Apple's AdServices endpoint and store the raw fields (orgIdcampaignIdadGroupIdkeywordIdadIdclaimTypeconversionTypecountryOrRegionclickDateimpressionDate) in an internal attribution table.

What lands on the customer object as reserved subscriber attributes depends on whether you have an Advanced Apple Ads integration set up (the one where you Sign in with Apple / authorize the Apple Search Ads Campaign Management API). The Advanced integration is what lets us resolve campaignId → campaignNameadGroupId → adGroupNamekeywordId → keyword text. That resolution job then writes the following reserved attributes:

Attribute Value

$mediaSource

"Apple Search Ads"

$campaign

Campaign name

$adGroup

Ad group name

$keyword

Keyword text (only when search match is disabled, since Apple doesn't return a keywordId for search-match-on traffic)

These match the same $mediaSource / $campaign / $adGroup / $keyword keys which can be used for AppsFlyer, Adjust, Branch, Tenjin, etc. They're documented in Customer Attributes → Attribution Data.

A few important caveats:

  • No Apple Ads integration, or only Basic: the AdServices token is collected and stored, and your Charts will still get the install/attribution signal, but no $mediaSource / $campaign / $adGroup / $keyword reserved attributes are written to the customer. Resolving names requires the Advanced integration's auth token.
  • Organic installs (Apple returns attribution: false) don't get any of these attributes set.
  • The $apple_search_ads_* style key shape you guessed at doesn't exist

2. Does this show up in webhook event.subscriber_attributes?

Yes. Once those reserved attributes are written, they're in the same subscriber_attributes map you already see on webhook events (alongside $idfa$idfv$ip$attConsentStatus, etc.). So on a webhook for a customer attributed to ASA via the Advanced integration, you should see entries like:

"subscriber_attributes": {

"$mediaSource": { "value": "Apple Search Ads", "updated_at_ms": ... },

"$campaign": { "value": "<Campaign Name>", "updated_at_ms": ... },

"$adGroup": { "value": "<Ad Group Name>", "updated_at_ms": ... },

"$keyword": { "value": "<Keyword>", "updated_at_ms": ... }

}

A couple of practical timing notes:

  • The AdServices → Apple Ads resolution runs asynchronously after we receive the token. Apple itself recommends allowing up to ~24h for attribution to be available, and we recommend allowing up to 7 days for full coverage. So a INITIAL_PURCHASE webhook fired immediately after install can land before these attributes are written. They'll be present on later events for the same subscriber.
  • The reason you don't see ASA attributes on your current customers is likely what you suspected: token collection isn't shipped to a public build yet, and TestFlight/sandbox usually returns placeholder values that we filter out.

3. Reading per-customer ASA attribution programmatically

You have three options that all read the same underlying reserved attributes:

  • Webhooks — event.subscriber_attributes as above. This is what we generally recommend for forwarding to your analytics.
  • Customer API v2 — GET /v2/projects/{project_id}/customers/{customer_id}/attributes returns the full attribute list, including the $mediaSource / $campaign / $adGroup / $keyword entries when set (API reference). The v1 /subscribers/{app_user_id} response also exposes them under subscriber.subscriber_attributes.
  • Scheduled Data Exports — the customer-level attribute fields (media_sourcecampaignad_groupkeyword) are exported per-row, so this is the easiest path if you're doing offline analysis or backfilling.

So the short version: set up the Advanced Apple Ads integration, ship token collection to a public build, and you'll see ASA attribution land in subscriber_attributes (and therefore in webhooks and the Customer API attributes list) under the standard reserved keys. Without the Advanced integration, ASA only powers Charts and Apple-Ads-specific destinations, not the per-customer attribute map.

Hope that helps!


Forum|alt.badge.img
  • Author
  • New Member
  • May 30, 2026

Thanks Chris, this fully answers my question — really appreciate the clear breakdown of how the Advanced Apple Ads integration controls whether ASA attribution surfaces in subscriber_attributes vs. only powering Charts.

That's exactly what I needed. 🙏