Revenue attribution
RevenueCat
Connect RevenueCat so App Store and Google Play purchases land on the channel that brought each app install, net of the store's commission.
ProductLense reads in-app purchases and subscriptions from RevenueCat: App Store, Google Play and the other stores RevenueCat supports. With the ProductLense app SDK, each purchase is credited to the campaign that brought the install. ProductLense only reads: it never grants, refunds or changes anything in RevenueCat.
What you need
| Field | Secret | Where to find it |
|---|---|---|
| Secret API key (v2) | Yes | RevenueCat → Project settings → API keys → + New secret API key, version 2, with read access to customer information. |
| Project ID | No | The proj… id in the dashboard URL or Project settings. |
| Webhook authorization header | Yes | Any long random value, at least 16 characters. You paste the same value into RevenueCat below. |
Every plan includes one billing connection per site, Free too; Growth and Scale allow any number. See plans and limits.
Set up
- In RevenueCat, create the v2 secret key above.
- In ProductLense, open your site's Settings → Billing connections → RevenueCat, paste the key, the project id and a new random authorization value, and click Connect and import history.
- Copy the webhook URL from the connection card.
- In RevenueCat → Integrations → Webhooks, add a webhook with that URL, paste the same value into Authorization header value, choose Production events and save.
Link purchases to app installs
In your app, pass ProductLense's install id to RevenueCat once, after both SDKs are configured:
| SDK | Call |
|---|---|
| React Native | Purchases.setAttributes(await ProductLense.revenueCatAttributes()) |
| Flutter | await Purchases.setAttributes(await ProductLense.revenueCatAttributes()) |
| iOS (Swift) | Purchases.shared.attribution.setAttributes(await ProductLense.revenueCatAttributes()) |
| Android (Kotlin) | Purchases.sharedInstance.setAttributes(ProductLense.revenueCatAttributes()) |
This sets the subscriber attribute pl_install_id. ProductLense maps it to that install's visitor, so a purchase is attributed to the deep link, Play Store campaign or other first touch of the install, even when the user never signs in. When the RevenueCat app user id is your own user id (not an anonymous $RCAnonymousID), ProductLense also matches it to the user id you pass to identify, which joins app and web purchases.
Webhook
URL: https://api.productlense.app/api/webhooks/revenuecat/<connection-id> (ProductLense shows the exact URL after you save).
Verification: RevenueCat sends the authorization value you set with every request, and ProductLense compares it in constant time. A missing or different value is refused. RevenueCat retries a failed delivery five times; each event id is processed once.
Events ProductLense uses:
| Event | ProductLense records |
|---|---|
INITIAL_PURCHASE, RENEWAL | a payment and the subscription as active (trials as trialing, with no payment) |
NON_RENEWING_PURCHASE | a one-time payment |
CANCELLATION | the subscription as canceled; with cancel_reason CUSTOMER_SUPPORT (a refund), a refund of that transaction |
REFUND_REVERSED | the refunded amount counted again |
EXPIRATION, BILLING_ISSUE, SUBSCRIPTION_PAUSED, PRODUCT_CHANGE, UNCANCELLATION | the subscription's status or plan |
Sandbox and test events are ignored.
What ProductLense reads
- History: on connect, the last 12 months. ProductLense walks your customers and reads each one's attributes, one-time purchases, subscriptions and, for App Store and Google Play subscriptions, every renewal transaction. Then a nightly reconcile keeps it current.
- Subscriptions from Stripe, RevenueCat Billing or promotional grants report only a lifetime total in RevenueCat's API, so their renewals are recorded from webhooks starting the day you connect. Connect Stripe directly for its history.
- Amounts stay in the purchase currency and are converted to USD at the European Central Bank rate for the day. History read from the API for one-time purchases is in USD, the only currency RevenueCat's API gives for them.
How fees are derived
The fee is the store's commission plus the tax the store remits, both as RevenueCat estimates them (commission_percentage and tax_percentage on webhooks, commission and tax in the API). ProductLense marks these fees as estimated, so net revenue matches RevenueCat's proceeds. A refund hands the commission and tax back, so a full refund nets to zero.
Limits
- RevenueCat's API allows 480 customer requests a minute, so the first import of a large project takes a while. ProductLense retries when it is rate limited.
- Family Sharing and offer-code purchases are recorded at the price RevenueCat reports.