Appstack
Integrate RevenueCat with Appstack for attribution and targeting
With our Appstack integration you can:
- Send RevenueCat subscription events directly to your Appstack webhook endpoint (optional).
- Attribute subscription revenue to campaigns tracked by Appstack using the Purchases SDK.
- Identify users in Appstack using the
$appstackIdsubscriber attribute.
The SDK integration (steps 1–2) and the webhook event forwarding (step 3) are independent. You can use the SDK attribution mapping without configuring webhook event forwarding, or enable both to get attribution mapping and event forwarding.
Event Forwarding Integration at a Glance
| Includes Revenue | Supports Negative Revenue | Sends Sandbox Events | Includes Customer Attributes | Sends Transfer Events | Optional Event Types |
|---|---|---|---|---|---|
| ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
1. Install the Appstack SDK
Before RevenueCat can integrate with Appstack, your app must be running the Appstack SDK. Refer to the Appstack developer documentation for the latest installation instructions.
2. Send attribution data to RevenueCat
The Appstack integration uses a reserved subscriber attribute to associate RevenueCat events with users in Appstack if the integration is configured to send events.
| Key | Description | Required |
|---|---|---|
$appstackId | The unique user identifier assigned by Appstack | ✅ |
Pass the dictionary returned by AppstackAttributionSdk.shared.getAttributionParams() (iOS) or AppstackAttributionSdk.getAttributionParams() (Android) directly to setAppstackAttributionParams(). This single call sets $appstackId, campaign attribution attributes ($mediaSource, $campaign, $adGroup, $ad, $keyword), click IDs (fbclid, gclid, ttclid, wbraid, gbraid), and device identifiers when appstack_id is present. You do not need to call collectDeviceIdentifiers() separately.
setAppstackAttributionParams() also automatically syncs the attributes to the RevenueCat backend and fetches fresh offerings before returning. This ensures Appstack-based targeting is applied before you display a paywall — the returned offerings already reflect the user's Appstack attribution data.
- Swift
- Kotlin
- Swift (async/await)
- Kotlin (Coroutines)
import AdSupport
// ...
Purchases.configure(withAPIKey: "public_sdk_key")
// ...
// Retrieve attribution params from the Appstack SDK
let attributionParams = AppstackAttributionSdk.shared.getAttributionParams()
// Forward to RevenueCat — syncs attributes and fetches fresh offerings
// so Appstack-based targeting is applied before the callback returns.
Purchases.shared.attribution.setAppstackAttributionParams(attributionParams) { offerings, error in
// Use `offerings` to present the correct paywall for this user
}
// ...
Purchases.configure(this, "public_sdk_key")
// ...
// Retrieve attribution params from the Appstack SDK
val attributionParams = AppstackAttributionSdk.getAttributionParams()
// Forward to RevenueCat — syncs attributes and fetches fresh offerings
// so Appstack-based targeting is applied before the callback returns.
Purchases.sharedInstance.setAppstackAttributionParams(
attributionParams,
object : SyncAttributesAndOfferingsCallback {
override fun onSuccess(offerings: Offerings) {
// Use `offerings` to present the correct paywall for this user
}
override fun onError(error: PurchasesError) { /* handle error */ }
}
)
import AdSupport
// ...
Purchases.configure(withAPIKey: "public_sdk_key")
// ...
// Retrieve attribution params from the Appstack SDK
let attributionParams = AppstackAttributionSdk.shared.getAttributionParams()
// Forward to RevenueCat — syncs attributes and fetches fresh offerings
// so Appstack-based targeting is applied before the await returns.
do {
let offerings = try await Purchases.shared.attribution.setAppstackAttributionParams(attributionParams)
// Use `offerings` to present the correct paywall for this user
} catch {
// handle error
}
// ...
Purchases.configure(this, "public_sdk_key")
// ...
// Retrieve attribution params from the Appstack SDK
val attributionParams = AppstackAttributionSdk.getAttributionParams()
// Forward to RevenueCat — syncs attributes and fetches fresh offerings
// so Appstack-based targeting is applied before the suspend function returns.
try {
val offerings = Purchases.sharedInstance.awaitSetAppstackAttributionParams(attributionParams)
// Use `offerings` to present the correct paywall for this user
} catch (e: PurchasesException) {
// handle error
}
Set these attributes after configuring the Purchases SDK and before the first purchase occurs.
This is enough for RevenueCat to start storing attribute subscription revenue information from Appstack.
If you are requesting the App Tracking permission through ATT to access the IDFA, call
setAppstackAttributionParams() again after the customer grants permission, passing
the latest params from AppstackAttributionSdk.shared.getAttributionParams().
The AdSupport framework is required to collect the IDFA on iOS.
3. Configure the Appstack integration in RevenueCat to forward events to Appstack
- Navigate to your project settings in the RevenueCat dashboard and choose Appstack from the Integrations menu.

- Enter your Webhook URL. The endpoint provided by Appstack to receive RevenueCat events.
- Enter the Authorization Header. The token provided by Appstack to authenticate incoming webhook requests.
RevenueCat will begin forwarding subscription events to your Appstack webhook endpoint.
Events sent to Appstack
The following RevenueCat event types are forwarded to Appstack:
| RevenueCat Event |
|---|
| Initial Purchase |
| Renewal |
| Cancellation |
| Uncancellation |
| Non-Renewing Purchase |
| Subscription Paused |
| Expiration |
| Billing Issue |
| Product Change |
| Transfer |
| Subscriber Alias |