Skip to content
Docs

Mobile

SKAdNetwork and AdAttributionKit

Receiving and verifying Apple privacy-preserving postbacks, conversion-value schemas, and mapping sources to campaigns.

On iOS, installs from users who deny App Tracking Transparency can only be measured with Apple's privacy-preserving attribution: SKAdNetwork (SKAN 2.0 to 4.0) and AdAttributionKit (AAK). Metrixed receives and verifies both, decodes conversion values you define, and maps sources to partners and offers.

Receiving postbacks

Point the app at your Metrixed SKAN host (the tracking domain that serves ingest):

  • Info.plist: NSAdvertisingAttributionReportEndpoint for SKAN and, for AdAttributionKit, AdAttributionKitReportEndpoint.
  • Ingest accepts them at POST /v1/skan/postbacks (aliases /v1/aak/postbacks, and Apple's developer-copy paths /.well-known/skadnetwork/report-attribution and /.well-known/appattribution/report-attribution). The body format (SKAN version, or an AAK signed JWS) is detected automatically.
  • Verification: SKAN postbacks are checked against Apple's public keys per version; AAK postbacks are an ES256 JWS verified against Apple's key set. Override keys with DT_SKAN_PUBLIC_KEYS (4.0=<base64>,3.0=<base64>,default=<base64>), fetch the AAK set from DT_AAK_KEYS_URL, or pin it with DT_AAK_JWKS. DT_SKAN_ACCEPT_UNVERIFIED=1 exists for development only.
  • Postbacks are de-duplicated on transaction id (or postback identifier) and sequence index, stored (/skan/postbacks) and mirrored to ClickHouse (skan_postbacks) for reporting. The event is mobile_skan_postback.

Source mapping

A postback identifies a campaign only by the ad network id and a 1 to 4 digit source identifier (SKAN 4 and AAK) or a campaign id (SKAN 3 and earlier). Mappings (/skan/mappings) turn these into a partner, offer and campaign name; a mapping without source_identifier is the network-level default, and one without app_id applies to every app.

Conversion-value schemas

You define what the 6-bit fine value (0 to 63) and the coarse value (low, medium, high) mean as a JSON schema of windows and rules, per app (/skan/cv-schemas). Windows follow SKAN 4: window 0 is days 0 to 2 (fine and coarse), window 1 is days 3 to 7 and window 2 is days 8 to 35 (coarse only).

json
{
  "version": 1,
  "windows": [
    { "window": 0, "lock_at_fine_gte": 60, "rules": [
      { "fine": 5,  "when": { "event": "register" } },
      { "fine": 20, "coarse": "medium", "when": { "event": "purchase", "count_gte": 1 } },
      { "fine": 45, "when": { "event": "purchase", "revenue_gte": "50" } }
    ] },
    { "window": 1, "rules": [ { "coarse": "high", "when": { "revenue_gte": "50" } } ] }
  ]
}

Rules: the highest matching fine value wins, values never decrease, coarse defaults to low (below 21), medium (below 42) or high from the fine value, and a rule with lock or reaching lock_at_fine_gte locks the window. Revenue thresholds are exact six-decimal decimals.

  • POST /skan/cv-schemas/simulate replays events against a draft schema.
  • POST /skan/cv-schemas/{id}/activate makes a schema the active one for its app (one active schema per app).
  • GET /skan/cv-schemas/{id}/decode-table lists what every value means.
  • The iOS SDK downloads the active schema from GET /sdk/v1/config (cached 6 hours), evaluates it on every event and calls Apple's update APIs (updatePostbackConversionValue, updateConversionValue, and AdAttributionKit's updateConversionValue). The server decoder and the SDK share test vectors (sdks/test-vectors/cv-schema.json), so both sides agree.
  • Decoded postbacks become events with estimated revenue from the schema that was active at receipt.

Reports

POST /reports/skan (admin) and POST /partner/reports/skan (partners) report postbacks by network, source, campaign, window and conversion value. Partners see only their own mapped traffic.

Limits worth knowing

Apple's key URL for AdAttributionKit has not been verified against a live Apple endpoint in this release, so pin the key set with DT_AAK_JWKS if you need certainty. Fine values are only delivered by Apple when crowd-anonymity thresholds are met, which is an Apple behaviour no tracker can change.