Skip to content
Documentation

Documentation

Google Play revenue

Real-time developer notifications through Pub/Sub, a service account to read each purchase, and the checklist for when nothing books.

How Play revenue reaches us

Google Play does not send a purchase to a URL directly. It publishes a message to a Pub/Sub topic in your Google Cloud project, and a push subscription on that topic delivers it to us. The message is thin -- it names the purchase token and the event, not the price or the buyer -- so we then ask the Play Developer API for the rest, using a service account you grant. Three Google-side pieces, and all three have to exist before a single sale books.

There is no shared secret for this webhook, deliberately. The amount, currency and buyer are read from Google's API, never from the notification body, so a forged notification would need a purchase token Google actually resolves -- and resolving one just re-books a real purchase that deduplication then rejects. The endpoint also refuses any notification whose packageName is not this app's.

Before you start

  • The app is on a Play track (internal testing is enough) and its package name on the App details tab matches the listing exactly.
  • Access to the Play Console and to a Google Cloud project as an editor. The Cloud project must be the one linked under Play Console → Setup → API access (link one there if none is).
  • The app sets obfuscatedAccountId on every purchase -- see your framework's SDK page. Without it sales book, but as unattributed.

1. The notification pipe (Google Cloud + Play Console)

  1. Google Cloud → Pub/Sub → Topics → Create topic. Any name, e.g. roas-play-notifications.
  2. On the topic → Permissions → Add principal: [email protected], role Pub/Sub Publisher. Play Console refuses the topic in step 5 without this.
  3. On the topic → Create subscription. Delivery type Push -- not Pull, which is the console's default and delivers nothing. Endpoint URL: copy it from the app's Revenue tab (*Or take Google Play revenue directly*). It has this shape:
  4. Google Cloud → APIs & Services → Enable APIs: enable the Google Play Android Developer API on this project. Without it every purchase lookup fails with SERVICE_DISABLED.
  5. Play Console → Monetise → Monetisation setup → Real-time developer notifications: paste the topic's full name, projects/<project-id>/topics/<topic>, Save, then Send test notification.
text
https://api.roassensor.com/api/tracking/webhooks/play/YOUR_PUBLIC_KEY
Push endpoints need no domain-ownership proof, only a valid certificate.

The test notification proves the whole pipe -- Play → Pub/Sub → us -- before a single purchase exists. We answer it 200 and deliberately book nothing.

2. The service account (the piece revenue depends on)

A notification acknowledges and Play stops retrying whether or not we could read the purchase. So a missing or under-permissioned service account fails silently: everything looks healthy and nothing books.

  1. Google Cloud → IAM → Service accounts → Create. Any name, e.g. roas-play-reader. No Cloud IAM role is needed.
  2. Keys → Add key → JSON. Download the file. This is the credential; treat it as one.
  3. Play Console → Users and permissions → Invite user: the service account's email address. Under App permissions, add this app and tick "View financial data, orders and cancellation survey responses". Linking the account elsewhere is not enough; without this exact permission Google answers *insufficient permissions*. A fresh grant can take a few minutes to take effect.
  4. In the panel → Revenue tab → Play service account → Add: paste the whole JSON file. It is saved as a connection on your account -- one service account covers every Android app in the same Cloud project -- and selected for this app.

3. Licence testers

Play Console → Setup → Licence testing. Accounts listed here purchase with *"Test card, always approves"* and are never charged. The setting is account-wide, not per app. Their purchases arrive flagged is_test, are attributed normally, and are excluded from every reported figure and from the conversions pushed back to your ad accounts.

Test subscriptions run on an accelerated clock (a yearly plan renews every 30 minutes), which is what lets you verify renewals in an afternoon.

What books, and what does not

Renewals are the revenue. Each one books as its own conversion, with its own order id, and credits the campaign that won the original install.

Play notificationTreatment
SUBSCRIPTION_PURCHASED (first period)Books revenue
SUBSCRIPTION_RENEWEDBooks revenue, as a separate conversion
SUBSCRIPTION_RESTARTED, SUBSCRIPTION_RECOVEREDBooks revenue
ONE_TIME_PRODUCT_PURCHASEDBooks revenue
Voided purchase (refund)Books a negative conversion reversing the original, even if the original touchpoint has since been pruned
CANCELED, EXPIRED, PAUSED, ON_HOLD, IN_GRACE_PERIOD, REVOKED, price-change and pause-schedule eventsAcknowledged, books nothing -- no money moved
Test notificationAcknowledged, books nothing

Two subscription cases need care:

  • A free trial books ₹0 / $0 on day one. SUBSCRIPTION_PURCHASED fires when the trial *starts*, and Play reports the plan's price rather than what was charged. The line item's offerPhase names the phase, so the trial period books zero -- still written, still attributed, so trial starts stay countable -- and the first paid period arrives later as its own notification.
  • Plan changes issue a fresh purchase token and report the *plan* price rather than the prorated amount actually charged. If your tiers can be switched mid-period, tell us.

When nothing books: the checklist

Work down in order. Each step points at exactly one fix, and the first three are where every stalled Play integration we have seen was stuck.

CheckWhereIf it is wrong
Did Send test notification succeed?Play Console → Monetisation setup → RTDN*Failed to send* = the topic lacks the Publisher grant, or the name is not the full projects/…/topics/… form, or the project is not the one linked under API access.
Is the topic receiving messages?Cloud → Pub/Sub → the topic → Metrics → *Published message count*0 = Play never published; fix the step above. > 0 = Play is fine, the subscription is not.
Is the subscription Push, to the right URL?Cloud → Pub/Sub → Subscriptions → the subscription*Pull* piles messages up and delivers nothing. Change it to Push with the URL from the Revenue tab. Undelivered messages are kept for seven days, so fixing it delivers the backlog.
Is the Play Developer API enabled?Cloud → APIs & Services → Google Play Android Developer APINotifications arrive and answer 200, but every lookup fails with SERVICE_DISABLED. Enable it.
Does the service account have *View financial data* on this app?Play Console → Users and permissionsLookups fail with *insufficient permissions*. Grant it; wait a few minutes.
Was the buyer a licence tester who bought through Play's purchase sheet?The deviceA purchase through your own payment gateway (UPI, a web checkout) never reaches Play, so Play never notifies anyone. That revenue must come from your server through the Conversions API instead.

If a purchase was made while a step above was wrong, we can re-resolve it once the step is fixed -- ask us, with the time of the purchase.