Skip to main content
Both SDKs ship from one public repository, Evo-Marketing-LLC/evo-attribution-sdk, with no dependencies. They report a single install, keep a persistent install ID, and connect later purchases to that ID. Neither one throws into your app. Every network and storage failure is contained and logged.

Install

In Xcode choose File → Add Package Dependencies…, paste the package URL, pick a dependency rule starting at 0.1.0, and add the EVOAttribution library to your app target.
Requires iOS 15 or later. The package uses only Foundation, UIKit and os.log. Source: Sources/EVOAttribution in the SDK repository.
Find your pixel key in the client portal under Results → Attribution, in the Developer setup section.

Configure

Call this once during app startup, before either tracking method.
An endpoint: argument is available for testing against a non-production API; it defaults to https://dialedapi.evomarketing.co.

Track the install

trackInstall persists an install UUID and reports successfully only once — the flag lives in UserDefaults (evo_install_reported) on iOS and in your storage adapter on React Native. A network failure leaves it pending, so the next launch retries. The call sends pixel_key, install_id, platform, the app version, an occurred_at timestamp, and the optional clipboard token and creator code.

The clipboard trade-off

Clipboard reading is opt-in because iOS may show a paste notification to the user. It is also the single highest-value signal you can send: The helper only uses clipboard strings beginning with evc_, so it never reads anything else the user copied. On React Native, clipboard support only exists if you passed getClipboard.

Creator codes

Pass the code the new user typed in the app when a link cannot carry the credit — word of mouth, a podcast mention, a screenshot.
A clipboard token still wins when both are present. See Creator codes.

What the install response contains

New installs return HTTP 201; idempotent retries return 200 with duplicate: true.
resolution_method is one of clipboard, code, ip, or unattributed. link, code, and creator are null for an unattributed install. A code-resolved install reports attributed: true with link: null, the matched code, and its creator.

Track a purchase

Purchases post to POST /api/public/attribution/events with source: "sdk" and the persistent install ID as external_user_id. transactionId is the server-side deduplication key and should come from the store or order — a retry of the same transaction is a no-op. A purchase without its own click token inherits the attribution its install already resolved: the same link, creator, code, resolution method, and confidence. Both methods take an optional trailing code argument, same as trackInstall.
If you already use RevenueCat, Superwall, Stripe, or Apple’s own notifications, you do not need trackPurchase — wire the billing connector instead and let the provider report revenue server-side.

Sandbox and TestFlight purchases

Purchases reported from a sandbox or TestFlight build must never count as revenue. Pass sandbox: true (Swift: trackPurchase(transactionId:amount:currency:sandbox:), or hand the verified StoreKit 2 transaction to trackPurchase(transaction:amount:currency:) and the environment is inferred; React Native: the sandbox option). Sandbox rows are kept so you can confirm the hookup in the portal, but every total reads live rows only.

The install ID

The install ID is a UUID generated on first launch and stored under evo_install_id. It is public by design, so subscription SDKs can carry it into their webhook payloads.
Add these right after you configure the provider’s SDK, and after configure/configureEvoAttribution has run. getEvoInstallId() throws if EVO attribution was never configured.

Apple direct (no RevenueCat or Superwall)

Pass the same UUID to StoreKit so Apple’s server notification carries it:
StoreKit 1 apps put the value in payment.applicationUsername instead. The Apple connector only accepts an appAccountToken that is a well-formed UUID.

Testing

With curl

Use a real brand pixel key. Re-running the first command returns 200 with duplicate: true.

On TestFlight

1

Open a real creator app link on the device

Tap Get the app so the click token reaches the clipboard, then install the TestFlight build.
2

Launch and check the install

trackInstall should return resolution_method: "clipboard" at 0.95. If it returns ip or unattributed, the clipboard handoff did not survive — usually an in-app browser.
3

Make a sandbox purchase

A StoreKit sandbox purchase flows through your billing connector and flips that connection to Connected, without appearing in the client’s conversion or revenue totals.
Purchases reported by trackPurchase are not flagged as sandbox — the SDK endpoint has no sandbox flag, so a TestFlight purchase reported that way lands as live revenue. Only provider webhooks carry the sandbox marker. Use throwaway amounts and be ready to clean up, or test purchases through a connector instead.

Resetting a device

trackInstall reports once per install. To test it again, delete the app (clearing UserDefaults) or clear your storage adapter’s evo_install_id and evo_install_reported keys.