Singular
Integrate Purchases SDK with Singular for precise revenue tracking
With our Singular integration you can:
- Accurately track subscriptions generated from Singular campaigns, allowing you to know precisely how much revenue your campaigns generate.
- Send trial conversions and renewals directly from RevenueCat to Singular, allowing for tracking without an app open.
- Continue to follow your cohorts for months to know the long tail revenue generated by your campaigns.
Integration at a glance
| Revenue support | Supports Negative Revenue | Sends Sandbox Events | Includes Customer Attributes | Sends Transfer Events | Optional Event Types |
|---|---|---|---|---|---|
| ✅ | ✅ | Requires sandbox SDK key | Matching only | ❌ | See Event types |
For a cross-provider view of identifiers, revenue support, sandbox behavior, and attribution responsibilities, see the attribution provider comparison.
Before you begin
Review Getting Started with Attribution Integrations for how attribution integrations fit together, then use the setup checklist as a reference for required lifecycle events, reporting choices, duplicate-event risks, and testing checks.
The following considerations are specific to Singular:
- Singular has two server-to-server Event API versions. Event Endpoint V2 is required for Singular accounts created on or after July 15, 2026. Event Endpoint V1 remains available only to eligible legacy Singular accounts created before that date. Choose the version in RevenueCat that matches your Singular account.
- Event Endpoint V2 requires the Singular Device ID (SDID) from the Singular SDK. RevenueCat cannot derive SDID with
collectDeviceIdentifiers(). Your app must pass SDID to RevenueCat withsetSingularDeviceID(). - If your app shows a paywall very early, a customer can purchase before SDID syncs to RevenueCat. Keep the Singular SDID callback in your implementation so
setSingularDeviceID()runs when SDID becomes available. - Keep the Singular SDK installed and initialized when you use Event Endpoint V2, or when you rely on Singular for install and session tracking in a hybrid integration.
- Turn off Singular SDK purchase or revenue tracking for the same subscription events RevenueCat sends, unless you intentionally manage deduplication in Singular.
- The Singular integration supports mobile App Store and Play Store events only. Stripe and other web billing events aren't sent to Singular.
- In Singular's Apps settings, do not enable Reject IAP without Receipt. RevenueCat validates purchases before sending events and doesn't include store receipts in the Singular payload.
- RevenueCat sends Singular events server-to-server and can't modify SKAdNetwork conversion values from those events.
1. Install the Singular SDK
Before RevenueCat can deliver events with Event Endpoint V2, your app must run the Singular SDK so it can generate SDID. Refer to the Singular developer documentation for the latest installation instructions.
If you use Event Endpoint V1 with platform device identifiers only, the Singular SDK is still recommended when Singular also tracks installs or sessions in your app.
2. Send attribution data to RevenueCat
Singular matches RevenueCat events using either SDID (Event Endpoint V2) or platform device identifiers (Event Endpoint V1). Configure the path that matches the Event API version you select in RevenueCat.
Event Endpoint V2 (recommended)
Use Event Endpoint V2 if your Singular account was created on or after July 15, 2026, or if Singular requires SDID for your account.
| Key | Description | Required |
|---|---|---|
$singularDeviceId | Singular Device ID (SDID) generated by the Singular SDK for this app install | ✅ |
Pass SDID to RevenueCat with setSingularDeviceID(). SDID isn't collected by collectDeviceIdentifiers() and can't be entered manually in the RevenueCat dashboard, because it's per device and per install. Set SDID after the RevenueCat SDK is configured and before the first purchase occurs whenever possible.
Consent changes such as App Tracking Transparency affect platform identifiers used by Event Endpoint V1, not the SDID required for Event Endpoint V2. If you use the legacy API, follow the Event Endpoint V1 (legacy) guidance for collectDeviceIdentifiers() and ATT.
The examples below show the recommended app-side flow:
- Configure the RevenueCat SDK.
- Initialize the Singular SDK.
- Pass SDID to RevenueCat with
setSingularDeviceID()in the Singular SDK's SDID callback when it becomes available. - Keep the SDID callback in place so
setSingularDeviceID()runs again when Singular provides or updates SDID, such as after SDK initialization or reinstall.
Use RevenueCat SDK 5.87.0+ on iOS or 10.19.0+ on Android when setting $singularDeviceId from your app.
- iOS
- Android
- None
- Register
sdidReceivedHandleron yourSingularConfigobject. Singular calls it when SDID is available, including SDIDs restored from a previous install. - See Singular's iOS SDK configuration reference.
- Register an
SDIDAccessorHandlerwithwithSdidAccessorHandler()and forward bothsdidReceivedanddidSetSdidto RevenueCat. - See Singular's Android SDK basic integration.
- Swift
- Kotlin
import RevenueCat
import Singular // Provides SingularConfig
// ...
Purchases.configure(withAPIKey: "public_sdk_key")
// ...
guard let config = SingularConfig(apiKey: "YOUR_SDK_KEY", andSecret: "YOUR_SDK_SECRET") else {
fatalError("Failed to create Singular config")
}
// Pass the SDID to RevenueCat when the Singular SDK makes it available.
config.sdidReceivedHandler = { sdid in
Purchases.shared.attribution.setSingularDeviceID(sdid)
}
Singular.start(config)
import com.revenuecat.purchases.Purchases
import com.singular.sdk.SDIDAccessorHandler
import com.singular.sdk.Singular
import com.singular.sdk.SingularConfig
// ...
Purchases.configure(this, "public_sdk_key")
// ...
val config = SingularConfig("YOUR_SDK_KEY", "YOUR_SDK_SECRET")
.withSdidAccessorHandler(object : SDIDAccessorHandler {
override fun sdidReceived(result: String) {
Purchases.sharedInstance.setSingularDeviceID(result)
}
override fun didSetSdid(result: String) {
Purchases.sharedInstance.setSingularDeviceID(result)
}
})
Singular.init(applicationContext, config)
Event Endpoint V1 (legacy)
Use Event Endpoint V1 only if your Singular account is eligible for Singular's legacy Event API and doesn't require SDID.
RevenueCat sends Singular events only when the required Customer Attributes below are set for the purchase platform.
| Key | Description | Required |
|---|---|---|
$idfa | iOS advertising identifier UUID | ✅ (iOS) |
$idfv | iOS vendor identifier UUID | ✅ (iOS) |
$gpsAdId | Google advertising identifier | ✅ (Android, one of $gpsAdId or $androidId) |
$androidId | Android device identifier | ✅ (Android, one of $gpsAdId or $androidId) |
$ip | The IP address of the device | ⚠️ (optional) |
These properties can be set manually, like any other Customer Attributes, or through collectDeviceIdentifiers(). Set them after the RevenueCat SDK is configured and before the first purchase occurs whenever possible.
The examples below show the recommended app-side flow:
- Configure the RevenueCat SDK.
- Call
collectDeviceIdentifiers(). - Collect device identifiers again if a new value becomes available, such as after ATT permission is granted.
- iOS
- Android
- None
- If you request App Tracking Transparency permission to access the IDFA,
call
collectDeviceIdentifiers()again after the customer accepts permission to update the$idfaattribute in RevenueCat. - The AdSupport framework is required to access the IDFA parameter. In
Xcode, add
AdSupport.frameworkto your app target under Frameworks, Libraries, and Embedded Content, leave it set to Do Not Embed, then importAdSupportin your Swift file.
- RevenueCat's current Android SDKs don't collect Android ID. Google's
Advertising ID (
$gpsAdId) acts as the primary Android device identifier in RevenueCat and when connecting with third-party integrations.
- Swift
- Kotlin
import RevenueCat
import AdSupport // Required for IDFA collection
// ...
Purchases.configure(withAPIKey: "public_sdk_key")
// ...
Purchases.shared.attribution.collectDeviceIdentifiers()
import com.revenuecat.purchases.Purchases
// ...
Purchases.configure(this, "public_sdk_key")
// ...
Purchases.sharedInstance.collectDeviceIdentifiers()
For endpoint URLs, transport differences, and field-level mapping between V1 and V2, see the Singular event delivery reference.
(Optional) Send campaign data to RevenueCat
RevenueCat isn't an attribution network and can't determine which ad drove an install or conversion. If Singular or another source gives your app final campaign values, you can attach them to the customer using reserved Customer Attributes.
Don't set temporary placeholders like Organic, Unknown, or No User Consent while waiting for final attribution. Reserved attribution attributes can only be set once per customer. If Singular later returns final campaign values, RevenueCat can't replace a placeholder you already set.
| Key | Description |
|---|---|
$mediaSource | The attribution source or network |
$campaign | The campaign name or identifier |
$adGroup | The ad group name or identifier |
$ad | The ad name or identifier |
$keyword | The keyword associated with the attribution |
$creative | The creative name or identifier |
3. Configure Singular in RevenueCat
After your app sends the required identifiers or SDID to RevenueCat, enable the integration in the RevenueCat dashboard.
- Go to your dashboard, and select your project.
- In the lower-left corner, select Integrations.
- Under Attribution, select Singular.
- Add your production SDK key from Settings → SDK in Singular.
- Add a sandbox SDK key. To prevent RevenueCat from sending sandbox events to your production environment in Singular, use a different SDK key from production.
- Select the Event API version that matches your Singular account:
- v2 for Singular accounts created on or after July 15, 2026, and for any account that requires SDID.
- v1 only for eligible legacy Singular accounts that still accept platform device identifiers without SDID.
- (Optional) Enable Report early renewals if you want RevenueCat to send a renewal's occurrence time when a store processes it early, instead of the time when the new subscription period is due to start.
- Configure event names for each lifecycle event RevenueCat should send, or choose the default event names.
- Select whether you want sales reported as gross revenue (before app store commission), or after store commission and/or estimated taxes. Use the same reporting mode when comparing Singular-side revenue to RevenueCat revenue metrics. Learn more about taxes and commissions.
Event types
RevenueCat sends the core subscription lifecycle events described in the setup checklist.
Singular also supports these optional events:
| Optional event | Sent when |
|---|---|
| Non-subscription purchase | A user makes a one-time (non-subscription) purchase |
| Uncancellation | A user re-enables auto-renew after cancelling |
| Subscription paused | A subscription enters a paused state |
| Expiration | A subscription expires and access is lost |
| Billing issue | RevenueCat detects a billing issue for the subscription |
| Product change | A user changes the product of their subscription |
For V1 and V2 request shapes, identifier requirements, and RevenueCat field mapping, see the Singular event delivery reference.
4. Test the Singular integration
Before rolling out the integration, test with a new customer after the SDK, customer attributes, and dashboard settings are configured.
-
Make a sandbox purchase with a new customer.
-
In the RevenueCat Customer Profile, confirm the required attributes from Send attribution data to RevenueCat are present. For Event Endpoint V2, confirm
$singularDeviceIdis set. For Event Endpoint V1, confirm the platform identifiers for the purchase store are set. -
In Customer History, open the sandbox purchase event and confirm the Singular delivery row exists. To compare the request with readable examples for your selected Event API version, see the Singular event delivery reference. If RevenueCat doesn't show a Singular delivery row, see no provider delivery row troubleshooting.
-
In Singular, verify the event in Export logs. Revenue from RevenueCat-delivered events may not appear in Singular's SDK console even when Singular processed the event as a revenue event in Export logs.
You should start seeing events from RevenueCat appear in Singular.