Attribloom
All integrations

Test iOS attribution

Prove the pipeline in sandbox, then confirm one real production sale, safely.

Live

What you are testing

A conversion travels: affiliate link, then a click, then install, then first-launch bind (Attribloom mints the appAccountToken), then the StoreKit purchase carries that token, then Apple sends a signed notification, then your server forwards it, then Attribloom verifies it and accrues the commission. This guide proves that whole chain.

For AI agents

If you are an agent wiring this up: read the iOS integration guide first for the endpoints and the code, then run Path A (sandbox) below. Every step lists the exact request and the exact response to assert on. Do not mark a step done until the observed response matches.

The environment gate is real

An Attribloom app is registered as either Sandbox or Production (appleEnvironment). A Production app rejects Sandbox notifications with 200 ignored_non_production and writes nothing. A Sandbox app accepts them and accrues as a test conversion (flagged, excluded from real payouts). Pick the environment that matches how you are buying.

Before you start

Prerequisites

  • Your app is registered in Attribloom and you have its surface id (the last path segment of the Forwarding URL).
  • Your server forwards App Store Server Notifications v2 to /v1/app-store/assn/:surfaceId, signed, with ATTRIBLOOM_FORWARDING_SECRET set to the same value as Attribloom.
  • Your app calls /v1/app-store/bind on first launch and sets the returned token on product.purchase(options:).
  • You have at least one affiliate link (https://attribloom.com/r/<code>) or a referral code to enter.

Path A. Sandbox or TestFlight (proves the full pipeline, safely)

Register the app in Attribloom with environment Sandbox. StoreKit sandbox subscriptions renew on an accelerated clock (minutes, not months), so you can watch a renewal and a refund-driven clawback in one sitting. Nothing here touches real money.

  1. 1

    Open an affiliate link

    Open https://attribloom.com/r/<code> so a click is recorded. Confirm the click lands (it returns the App Store interstitial).

  2. 2

    Install and launch from TestFlight

    On first launch your app should call /v1/app-store/bind. Assert the response is 200 with a non-empty appAccountToken, and that you persisted it to the Keychain.

  3. 3

    Make a StoreKit sandbox purchase

    Buy the subscription with a Sandbox Apple Account (Settings, Developer, Sandbox Apple Account). Confirm transaction.appAccountToken equals the token from bind.

  4. 4

    Forward the notification

    Apple sends a SUBSCRIBED notification to your server. Your forwarder relays the signedPayload to /v1/app-store/assn/:surfaceId. Assert the response is 200.

  5. 5

    Check the accrued conversion

    Because the app is Sandbox, the status is ok (or trial for an introductory free trial) and a test conversion appears on the app's Attribution view. Real payouts exclude it.

  6. 6

    Force a refund and watch the clawback

    Refund the sandbox transaction (or let it expire). Apple sends REFUND / EXPIRED; the forwarded notification reverses the commission on the ledger. Assert the balance returns to zero.

Testing against a Production app instead?

If your Attribloom app is registered Production and you send a Sandbox purchase, the assn returns 200 ignored_non_production and nothing accrues. That is the environment gate doing its job, not a bug. Register a Sandbox app to see accruals from sandbox purchases.

Path B. Production (confirms one real sale)

A real Production accrual only exists after a real App Store purchase on a live build. TestFlight and every sandbox mechanism emit environment: Sandbox, so there is no way to produce a Production notification ahead of shipping. Once the instrumented build is live, buy your own subscription through a referred link.

The hold makes a self-test safe

A matured commission is held 7 to 60 days before it is payable (see the commission hold period). A test purchase cannot pay out in that window, so refund it after you confirm attribution and the clawback reverses the accrual. No money leaves.

  1. 1

    Register the app as Production

    Set environment to Production and complete verification (Attribloom asks Apple to send a signed test notification with your App Store Server API key and flips the app to Active when it arrives).

  2. 2

    Buy through a referred link

    Open your affiliate link, install the live build, and purchase the subscription for real. Confirm the token bound on first launch.

  3. 3

    Confirm the real accrual

    The forwarded SUBSCRIBED notification returns status ok and a real conversion appears, attributed to the affiliate, with commission computed on net proceeds (excluding trial, refund, and tax).

  4. 4

    Refund to close the loop

    Refund the purchase from App Store Connect. The REFUND notification claws the commission back before the hold elapses, so nothing is ever paid out.

Responses to assert on

statusHTTPMeaning
ok200Verified, matched an affiliate, commission accrued (real for a Production app, test for a Sandbox app).
trial200Verified and recognized, but a free trial, so nothing accrues yet. Accrues when it converts to paid.
duplicate200Already processed. Delivery is idempotent, so retries and Apple re-sends are safe.
unattributed200Verified, but no affiliate token on the transaction. Nothing to credit.
ignored200Not a relevant notification type (for example a TEST notification, which carries no transaction).
ignored_non_production200A Sandbox notification reached a Production-registered app. Dropped, zero ledger. Expected when testing sandbox purchases against a prod app.

Troubleshooting

SymptomCause and fix
assn returns 401HMAC mismatch or clock skew over 300s. Confirm ATTRIBLOOM_FORWARDING_SECRET matches byte for byte, timestamp is unix seconds, and the signature is sha256= + hex over "${ts}." + rawBody.
assn returns 400The signedPayload was re-encoded or pretty-printed. Forward Apple's JWS string verbatim.
status ignored_non_productionYou sent a Sandbox purchase to a Production app. Register a Sandbox app, or buy through the App Store for real.
status unattributedNo appAccountToken on the transaction. The bind did not run, or the token was not set on product.purchase(options:). Check first-launch bind and the purchase call site.
No notification arrivesYour app's App Store Server Notifications v2 URL is not set, or your forwarder is not relaying. Use App Store Connect, Request a Test Notification, and confirm your forwarder gets a 200 ignored (not 401/400).

Start in sandbox to prove the pipeline, then confirm one real production sale. See the iOS integration guide for the endpoints and code.

Further reading

Get startedI'm an affiliateTalk to us