Skip to content
Documentation

Documentation

RevenueCat

One webhook for both stores, if RevenueCat already runs your subscriptions.

When to use it

If RevenueCat already manages your in-app purchases, its webhook is the shortest route: one endpoint, one header, and both stores' purchases, renewals and refunds arrive as a single kind of event. You then need neither the Google Play nor the App Store setup.

Setup

  1. Revenue tab → Connect RevenueCat. Choose any value for the Authorization header and Save. It is a shared secret: we compare it constant-time on every event.
  2. RevenueCat → Project settings → Integrations → Webhooks → Add. URL: the one on the Revenue tab. Authorization header: the same value.
  3. Press RevenueCat's Send test event. Within seconds the Revenue tab moves from *Waiting for the first event* to confirming the URL, without waiting for a real purchase.
text
https://api.roassensor.com/api/tracking/webhooks/revenuecat/YOUR_PUBLIC_KEY

The buyer link

RevenueCat identifies a customer by app_user_id. Configure it with our visitor id, and every event carries the thread back to the install:

kotlin
// Kotlin
Purchases.configure(PurchasesConfiguration.Builder(context, apiKey).appUserID(Roas.visitorId()).build())

// Swift
Purchases.configure(withAPIKey: apiKey, appUserID: Roas.visitorId())
visitorId() is null before the SDK has initialised; initialise ours first.

Both SDKs are initialised at launch, so this is an ordering, not a race: ours first, then RevenueCat with the id ours returns.

What books, and what does not

RevenueCat eventTreatment
INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASEBooks revenue; each renewal separately
CANCELLATION (a refund)Books a negative conversion reversing the original
EXPIRATION, BILLING_ISSUE, TRANSFER, PRODUCT_CHANGE, TEST, …Acknowledged, books nothing

Events with environment: SANDBOX -- a StoreKit tester or a Play licence tester -- are flagged is_test and kept out of reported figures. An event missing the field is treated as real money, deliberately: dropping genuine revenue on the strength of a field that was not sent is the more expensive mistake.

Each renewal is credited like the sale that started its subscription (same campaign, ad group and keyword), however many months later it lands, while Renewals follow the subscriber is on in the app's Attribution tab. It is on by default.

Importing your history

The webhook only reports sales from the day it was connected. Revenue tab → Import RevenueCat history brings in everything before that from RevenueCat's API, so the Apple Search Ads page shows last year's revenue per keyword on the first day.

  1. RevenueCat → Project settings → API keys → New secret key, version V2, with read access to apps, products, customers, subscriptions and purchases.
  2. Paste the key and the project ID, press Find apps, and pick the RevenueCat app that is this one (the one whose bundle id matches is preselected).
  3. Press Import history. It runs in the background: RevenueCat allows about 400 requests a minute, so a large app takes a while, and the card shows progress.

One sale per real payment, on the day it was paid, renewals included, in US dollars as RevenueCat converted them. A payment already received through the webhook or App Store notifications is skipped, never counted twice. Customers RevenueCat holds Apple Ads attribution for are credited to that campaign, ad group and keyword.