# Google Play subscription tracking

<Aside type="caution" icon="setting" title="Developer assistance needed">
You'll need help from your development team to set up this integration. Please share this guide with them.
</Aside>

## Integration overview

[Real-Time Developer Notifications (RTDN)](https://developer.android.com/google/play/billing/rtdn-reference) is Google Play's server-to-server service that sends a real-time message whenever a subscription's status changes.

By connecting Google Play RTDN to Pushwoosh, you can react to the entire subscription lifecycle, including purchases, renewals, cancellations, billing problems, expirations, and refunds — without building your own backend infrastructure. Whenever a subscription's status changes in a user's Google Play account, Google notifies Pushwoosh, and Pushwoosh fires the matching [`PW_Subscription*`](#tracked-events) event on the user profile.

<Aside type="note">
This integration supports **Android subscriptions** (Google Play RTDN). To track iOS subscriptions, see [App Store subscription tracking](/product/integrations/app-store-subscription-tracking/).
</Aside>

### Integration type

**Source:** Real-Time Developer Notifications are sent from Google Play to Pushwoosh.

### Tracked events

Pushwoosh maps every supported Google Play notification to a unified `PW_Subscription*` event set, so you can trigger campaigns on any stage of the subscription lifecycle.

| Event | Fires when |
| ----- | ---------- |
| `PW_SubscriptionStart` | A user buys the subscription for the first time. |
| `PW_SubscriptionRenew` | The subscription auto-renews for a new billing period. |
| `PW_SubscriptionCancel` | A user turns off auto-renewal. The subscription stays active until it expires. |
| `PW_SubscriptionResume` | A user restarts the subscription before it lapses. |
| `PW_SubscriptionBillingIssue` | A renewal payment fails and the subscription enters its grace period. |
| `PW_SubscriptionRecovered` | A previously failed renewal goes through and the subscription is active again. |
| `PW_SubscriptionExpired` | The subscription has fully lapsed and is no longer active. |
| `PW_SubscriptionRefund` | Google Play revokes the subscription (for example, after a refund). |

Every event carries the same attributes:

- **productID:** the Google Play product identifier of the subscription.
- **expiresAt:** when the current paid period ends, as a Unix timestamp in seconds. Included when Google provides it.

<details>

<summary>How events map to Real-Time Developer Notifications</summary>

For developers verifying the integration, each Pushwoosh event corresponds to these RTDN `notificationType` values:

| Pushwoosh event | RTDN `notificationType` |
| --------------- | ----------------------- |
| `PW_SubscriptionStart` | `SUBSCRIPTION_PURCHASED` (4) |
| `PW_SubscriptionRenew` | `SUBSCRIPTION_RENEWED` (2) |
| `PW_SubscriptionCancel` | `SUBSCRIPTION_CANCELED` (3) |
| `PW_SubscriptionResume` | `SUBSCRIPTION_RESTARTED` (7) |
| `PW_SubscriptionBillingIssue` | `SUBSCRIPTION_IN_GRACE_PERIOD` (6) |
| `PW_SubscriptionRecovered` | `SUBSCRIPTION_RECOVERED` (1) |
| `PW_SubscriptionExpired` | `SUBSCRIPTION_EXPIRED` (13) |
| `PW_SubscriptionRefund` | `SUBSCRIPTION_REVOKED` (12) |

Other notification types, such as on-hold, price changes, deferrals, and pauses, are acknowledged but don't post an event.

</details>

### How it works

A Google Play notification carries no Pushwoosh identifier. It includes only a purchase token and the app's `packageName`. So your app tags each purchase with the identifier Pushwoosh needs, and Pushwoosh reads it back from the purchase whenever a notification arrives.

1. A subscription's status changes in a user's Google Play account (a purchase, renewal, cancellation, and so on).
2. Google Play publishes an RTDN message to Pushwoosh's shared topic.
3. Pushwoosh reads the purchase's `obfuscatedAccountId`, which your app set to `<AppCode>:<hwid>` at purchase time.
4. Pushwoosh resolves the device whose HWID matches, finds the user bound to it, and posts the matching `PW_Subscription*` event for that user.

<Aside type="caution" title="Important">
The match between a Google Play purchase and a Pushwoosh user relies on the `obfuscatedAccountId`. If your app doesn't set this value at purchase time, Pushwoosh receives the notification but **no event is posted**. It is set at purchase and **cannot be backfilled** for existing subscriptions. See [how to set the account identifier](#set-the-account-identifier-at-purchase).
</Aside>

### Use cases

**Win back churning subscribers:** Disabling auto-renewal doesn't end access right away. The subscription stays active until the paid period ends, and that's your window to win the user back. On `PW_SubscriptionCancel`, launch a [Customer Journey](/product/customer-journey/pushwoosh-journey-overview/) with a retention push, an [email](/product/messaging-channels/emails/) about features they'd lose, or an [in-app message](/product/messaging-channels/in-apps/) with a renewal discount before access lapses.

**Onboard new subscribers:** Trigger a welcome series on `PW_SubscriptionStart` to help users get value from their plan early and set the stage for renewal.

**Rescue failed payments:** When `PW_SubscriptionBillingIssue` fires, a renewal payment didn't go through and the subscription is in its grace period. Prompt the user to update their payment method before they lose access, and follow up with `PW_SubscriptionRecovered` to confirm once it's resolved.

**Re-engage lapsed users:** Start a reactivation campaign on `PW_SubscriptionExpired` with a returning-customer offer for subscribers who have fully churned.

## Setting up the integration

Before you start, make sure you have a Pushwoosh app with [FCM configured](/developer/pushwoosh-sdk/android-sdk/firebase-integration/integrate-pushwoosh-android-sdk/) (already required for push), a Google Play app with a subscription, and Play Console admin access.

### Set the account identifier at purchase

Pushwoosh identifies the right user from the device's **HWID**, combined with your **Application Code**. The Pushwoosh Android SDK exposes a helper, `getSubscriptionAccountId()`, that returns this value already formatted as `<AppCode>:<hwid>`. Pass it to `BillingFlowParams.setObfuscatedAccountId()` when you launch the Google Play billing flow.

<Tabs>
<TabItem label="Kotlin">
```kotlin
val billingParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    // Tag the purchase with the Pushwoosh account identifier "<AppCode>:<hwid>"
    .setObfuscatedAccountId(Pushwoosh.getInstance().subscriptionAccountId)
    .build()

billingClient.launchBillingFlow(activity, billingParams)
```
</TabItem>
<TabItem label="Java">
```java
BillingFlowParams billingParams = BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        // Tag the purchase with the Pushwoosh account identifier "<AppCode>:<hwid>"
        .setObfuscatedAccountId(Pushwoosh.getInstance().getSubscriptionAccountId())
        .build();

billingClient.launchBillingFlow(activity, billingParams);
```
</TabItem>
</Tabs>

<Aside type="note">
Call `getSubscriptionAccountId()` after the SDK is initialized. It returns an empty string if the Application Code or HWID isn't available yet. Google limits the obfuscated account id to 64 characters. The Pushwoosh `<AppCode>:<hwid>` value stays within that limit.
</Aside>

<Aside type="caution">
If your app overrides the Pushwoosh HWID with a custom value, `getSubscriptionAccountId()` reflects it automatically. Don't build the identifier by hand. Always use the helper so the value matches the device's HWID in Pushwoosh, or the event cannot be attributed.
</Aside>

### Point Real-Time Developer Notifications at Pushwoosh

1. In [Google Play Console](https://play.google.com/console/), go to **Monetize → Monetization setup**.
2. Find **Real-time developer notifications** and set the **Topic name** to:

```
projects/pw-playstore-subscriptions/topics/play-rtdn
```

3. Click **Save**. Publish permission is already granted to Google's notification service, so there's nothing else to configure here.

### Grant Pushwoosh's service account

1. In Google Play Console, go to **Users and permissions → Invite new user**.
2. Enter the Pushwoosh service account email:

```
play-api@pw-playstore-subscriptions.iam.gserviceaccount.com
```

3. Under **App permissions**, add your app and grant **View financial data, orders, and cancellation survey responses** (plus the read-only app information permission).
4. Click **Save**. A service account doesn't need to accept the invite. Access is active immediately.

### Confirm the events in Pushwoosh

Pushwoosh registers each `PW_Subscription*` event in your project the first time it occurs, with the `productID` and `expiresAt` attributes. After a test, open **Audience → Events** to verify the events appear. They are then ready for segmentation, statistics, and Customer Journeys.

### Build your campaign

Create a [Customer Journey](/product/customer-journey/pushwoosh-journey-overview/) with a [trigger-based entry](/product/customer-journey/journey-elements/entry-elements/trigger-based-entry/) on any `PW_Subscription*` event, for example `PW_SubscriptionCancel` for win-back or `PW_SubscriptionStart` for onboarding, and add the messages you want to send.

## Testing

To verify the integration end to end:

1. In Google Play Console, open **Monetization setup** and click **Send test notification**. It should report success, confirming the topic is wired correctly.
2. Make a subscription purchase with the account identifier set as described above (this fires `PW_SubscriptionStart`), then cancel it from **Play Store → Subscriptions → Cancel** (this fires `PW_SubscriptionCancel`).
3. In Pushwoosh Control Panel, open the user profile and go to [Events history](/product/audience-data-and-segmentation/user-explorer/#events-history-tab).
4. Confirm that the events appear within a few moments.