# Singular

Connect Singular to receive Superwall subscription lifecycle and revenue events, with SDID support for stronger attribution.

In the **Analytics** section within **Integrations**, you can connect your Singular account to Superwall.

Use this integration when Singular is your attribution or marketing analytics destination and you want Superwall subscription events delivered there automatically.

## Features

* **Subscription lifecycle events**: Sends trials, subscription starts, renewals, cancellations, expirations, billing issues, product changes, refunds, and one-time purchases.
* **Revenue tracking**: Includes amount and currency for paid subscription events when revenue is available.
* **SDID-first attribution**: Uses Singular Device ID (SDID) when you pass it to Superwall.
* **Device ID fallbacks**: Uses supported iOS and Android identifiers when SDID is not available.
* **Sandbox controls**: Keeps sandbox events separate by using a sandbox SDK key, or skips sandbox events when one is not configured.
* **Superwall context**: Includes key Superwall event details such as product, transaction, user, store, environment, and country.

## Configuration

Singular requires an SDK key to accept server-side events from Superwall. Configure the production key, and optionally configure a sandbox key if you want test transactions to appear in Singular.

| Field              | Description                                                                            |
| ------------------ | -------------------------------------------------------------------------------------- |
| Production SDK key | Your Singular SDK key for production events.                                           |
| Sandbox SDK key    | Optional. Used for sandbox events. If blank, sandbox events are skipped.               |
| Sales reporting    | Choose **Revenue** for gross revenue or **Proceeds** for net revenue after store fees. |
| Anonymous users    | Optional. Choose whether to send events that do not have an app user ID.               |

## SDK Setup

Superwall forwards subscription events to Singular after they happen. Your app should already initialize the Singular SDK, or otherwise create Singular sessions, so Singular can connect later subscription events to the right device.

For the strongest attribution match, pass Singular Device ID (SDID) to Superwall as soon as Singular makes it available.

> **Note:** Singular requires account enablement for iOS and Android SDID usage. If your Singular SDK setup
> does not expose SDID retrieval, contact Singular before relying on SDID attribution.

Singular documents SDID retrieval in its [device ID guide](https://support.singular.net/hc/en-us/articles/4411780525979-Types-of-Device-IDs), [iOS SDK configuration reference](https://support.singular.net/hc/en-us/articles/42098616285339-iOS-SDK-Configuration-Methods-Reference), and [Android SDK configuration reference](https://support.singular.net/hc/en-us/articles/37157782717851-Android-SDK-Configuration-Methods-Reference).

### iOS

```swift
// After Singular returns an SDID
Superwall.shared.setIntegrationAttributes([
    .singularDeviceId: sdid
])
```

### Android

```kotlin
import com.superwall.sdk.models.attribution.AttributionProvider

// After Singular returns an SDID
Superwall.instance.setIntegrationAttributes(
    mapOf(AttributionProvider.SINGULAR_DEVICE_ID to sdid)
)
```

### Other SDKs

If your Superwall SDK does not yet expose a typed Singular integration attribute, set `singularDeviceId` as a user attribute instead.

```swift
Superwall.shared.setUserAttributes([
    "singularDeviceId": sdid
])
```

```kotlin
Superwall.instance.setUserAttributes(
    mapOf("singularDeviceId" to sdid)
)
```

```dart
await Superwall.shared.setUserAttributes({
  'singularDeviceId': sdid,
});
```

Superwall also accepts `sdid` as a raw user-attribute alias, but `singularDeviceId` is the recommended key.

## Device Identification

Superwall uses the best available Singular-compatible identifier for each event.

| Priority | Identifier                   | Notes                                                                                 |
| -------- | ---------------------------- | ------------------------------------------------------------------------------------- |
| 1        | `singularDeviceId` or `sdid` | Preferred. Uses Singular's SDID flow.                                                 |
| 2        | iOS `idfv`                   | Used when SDID is unavailable. `idfa` and `attStatus` are included when present.      |
| 3        | Android `googleAppSetId`     | Used when SDID is unavailable. `advertisingId` or `gpsAdid` is included when present. |

Events are skipped when Superwall cannot find SDID or the required platform fallback identifier. Events are also skipped when no operating system version is available from the event payload or user attributes.

## Event Mapping

Superwall maps subscription lifecycle events to Singular-friendly event names. The most important mappings are:

| Superwall lifecycle                    | Singular event name        |
| -------------------------------------- | -------------------------- |
| Trial start                            | `sng_start_trial`          |
| Trial end                              | `sng_end_trial`            |
| Subscription start or trial conversion | `sng_subscribe`            |
| Renewal                                | `subscription_renewed`     |
| Cancellation                           | `subscription_cancelled`   |
| Uncancellation                         | `subscription_uncancelled` |
| Expiration                             | `subscription_expire`      |
| Pause                                  | `subscription_pause`       |
| Billing issue                          | `billing_issue`            |
| Product change                         | `product_change`           |
| One-time purchase                      | `sng_ecommerce_purchase`   |
| Refund                                 | `subscription_refunded`    |

Refund detection takes precedence over other lifecycle mappings.

## Revenue Tracking

Superwall includes revenue on paid events when the calculated amount is at least `0.001`.

| Setting      | What Singular receives                                            |
| ------------ | ----------------------------------------------------------------- |
| **Revenue**  | Gross revenue in the purchased currency.                          |
| **Proceeds** | Net revenue after store fees, based on Superwall's event payload. |

Revenue events include the amount, currency, product identifier, and transaction identifier. Refund events use the refund event name, but do not include revenue fields.

## Platform Support

| Store        | Behavior                                                      |
| ------------ | ------------------------------------------------------------- |
| App Store    | Sent as iOS events.                                           |
| Google Play  | Sent as Android events.                                       |
| Stripe       | Sent only when the event includes an iOS or Android platform. |
| Other stores | Skipped.                                                      |

## Sandbox Handling

Sandbox events use the sandbox SDK key. If you do not configure one, Superwall skips sandbox events instead of sending them with the production key.

Sandbox events still include Superwall's sandbox environment context, so you can separate test traffic from production traffic in Singular.

## Troubleshooting

### Events are not appearing in Singular

1. Confirm the production SDK key is configured.
2. For sandbox events, confirm the sandbox SDK key is configured.
3. Confirm your app initializes Singular and creates Singular sessions.
4. Set `singularDeviceId` before subscription events occur.
5. If SDID is unavailable, confirm fallback identifiers are present: iOS needs `idfv`; Android needs `googleAppSetId`.
6. Confirm an operating system version is available.

### Revenue is missing

1. Confirm the event has a calculated amount of at least `0.001`.
2. Confirm the event includes a currency code.
3. Check whether sales reporting is set to **Revenue** or **Proceeds**.

### SDID attribution is missing

1. Confirm the Singular SDK returns SDID before the purchase flow.
2. Confirm Singular has enabled SDID usage for your account and app.
3. Confirm Superwall receives the value as `singularDeviceId` or `sdid`.