Get started

RevenueCat

If your app uses RevenueCat, connect its webhook and Unolink receives every trial, purchase, renewal, cancellation and refund straight from RevenueCat, including renewals and refunds that happen when the app isn't even open. Revenue in your funnel becomes net of refunds. Pro plan and up.

1. Connect

In Unolink, open your app → Settings → RevenueCat → Connect. Copy the webhook URL and the authorization header value (shown once).

2. Add the webhook in RevenueCat

In RevenueCat, open your project → Integrations → Webhooks → Add new configuration:

  • Webhook URL and Authorization header value: paste them.
  • Environment: both. Sandbox purchases are counted as test devices, so they stay out of your real numbers.
  • App: this app. Events: all.

Save, then Send test event. The RevenueCat card in Unolink shows when it arrives.

Purchases are joined to the install (and the link it came from) through the user ID your app reports: RevenueCat's own app user ID. With SDK 0.3.2 or later, one line keeps it current. Call it once at launch, before or after configure:

Unolink.connectRevenueCat { Purchases.isConfigured ? Purchases.shared.appUserID : nil }
Unolink.connectRevenueCat { Purchases.sharedInstance.appUserID }
import Purchases from "react-native-purchases"

Unolink.connectRevenueCat(Purchases)
Unolink.connectRevenueCat(
  () => Purchases.appUserID,
  addListener: Purchases.addCustomerInfoUpdateListener,
  removeListener: Purchases.removeCustomerInfoUpdateListener,
);

Unolink reads the ID at launch, whenever the app comes back to the foreground and whenever it changes, and sends it only when it's new. It doesn't add RevenueCat to your app: you hand RevenueCat in. On iOS and Android, also call Unolink.revenueCatUserChanged() after Purchases.logIn and Purchases.logOut to send the new ID at once (otherwise it goes with the next event). React Native and Flutter notice the change by themselves.

Without connectRevenueCat (an older SDK, or if you'd rather do it yourself), call setUserId with RevenueCat's ID after Purchases.configure, after every Purchases.logIn and Purchases.logOut, and on every launch. Use one or the other, not both:

Unolink.setUserId(Purchases.shared.appUserID)
Unolink.setUserId(Purchases.sharedInstance.appUserID)
Unolink.setUserId(await Purchases.getAppUserID())
Unolink.setUserId(await Purchases.appUserID);

For a guest, that's RevenueCat's anonymous ID, so a purchase made before signing up joins the install right away. After logIn, it's the account's ID. Unolink keeps every ID an install has reported, so the guest's purchase stays joined.

If your app only reports the account ID, a guest's purchase still joins, but only with RevenueCat's next event for that customer that lists both IDs (for example the first renewal). Until then the person shows as not paid yet. Reporting RevenueCat's ID avoids that wait.

When someone taps "continue as guest", call Unolink.signUpSkipped() too (SDK 0.3.2 or later, React Native 0.3.1; older SDKs: track("sign_up_skipped")), so the funnel's Continued as guest step counts them. See Guests and accounts.

Unolink never stores the ID itself, only a keyed hash that's different for each of your apps. A purchase that arrives before the app has reported its user waits, and joins the install as soon as it does. Payments that come days or weeks later still count, and the Report shows how long people take: see Payments and user IDs, which also covers privacy and Apple's rules.

What arrives

RevenueCatIn Unolink
INITIAL_PURCHASE (trial)Started trial
INITIAL_PURCHASE, NON_RENEWING_PURCHASE, trial conversionPaid, with revenue
RENEWALRenewed, with revenue
CANCELLATION (refund)Refunded, revenue subtracted
CANCELLATION, EXPIRATION, BILLING_ISSUECancelled subscription, Subscription expired, Billing issue

Once RevenueCat is connected it is the source of truth for purchases and trials: if your app also calls Unolink.purchase() or trialStarted(), those calls are ignored, so nothing is counted twice. Renewals, cancellations and the rest can be added as funnel steps in any funnel (Funnel → Edit).