Skip to content
Documentation

Documentation

Google Play revenue

Two pastes in Play Console with the managed setup, or your own Pub/Sub topic and service account -- 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, 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 that has been invited to your Play Console. Three Google-side pieces, and all three have to exist before a single sale books.

There are two ways to provide them, and the app's Revenue tab is where you choose. With the managed setup the topic and the service account are ours: you invite our account and paste our topic, and a Verify button proves both before the first purchase. With your own Google Cloud project you build all three yourself and point the push at your app's notification URL. Both book identically -- the same renewals, refunds, trials and test purchases, through the same code -- so the choice is only about who owns the plumbing, and it can be changed later without losing anything already booked.

There is no shared secret for either 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 managed endpoint additionally accepts only pushes Google signed for our own subscription, and every notification is routed by its packageName to the app whose owner verified it.

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 as an admin (to invite a user). For your own project you also need a Google Cloud project as an editor.
  • The app sets obfuscatedAccountId on every purchase -- see your framework's SDK page. Without it sales book, but as unattributed.

The managed setup (recommended)

On the app's Revenue tab choose Managed by ROAS Sensor. The tab shows a service account email and a topic name; nothing is created in Google Cloud on your side, because Play Console allows the notification topic to live in any Cloud project, and the service account can be invited from any project.

  1. Play Console → Users and permissions → Invite new users. Paste the service account email from the Revenue tab. Under App permissions add this app and tick "View app information and download bulk reports" and "View financial data, orders and cancellation survey responses". The second is the one revenue depends on; without it Google answers *insufficient permissions* and nothing books.
  2. Play Console → Monetise with Play → Monetisation setup → Google Play Billing. Turn on real-time developer notifications, paste the topic name from the Revenue tab, choose Subscriptions, voided purchases and all one-time products, Save -- then click Send test notification.
  3. Back on the Revenue tab, press Verify. It checks that we can read this app's purchases with the account you invited, and that a notification (the test counts) has reached our topic. Each check that fails says which Play Console screen fixes it.

A notification that arrives before you press Verify is held, not dropped, and books the moment verification passes -- so pasting the topic first, the natural order, loses nothing. Only one workspace can verify a given package name; the check that we can read your app is Google confirming you own it.

Using your own Google Cloud project

Choose Your own Google Cloud project on the Revenue tab. You build the topic, the push subscription and the service account, and point the push at the app's own notification URL. The rest of this page is that path.

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 managed setup

Everything the managed setup can get wrong is on the Revenue tab, because both halves of it are checks. Press Verify first -- it names the failing half and the screen that fixes it -- then work down this table.

SymptomWhat it meansThe fix
Verify: Play access ✗Google will not let our service account read this app.Play Console → Users and permissions: is the account listed, is this app under App permissions, and is *View financial data, orders and cancellation survey responses* ticked? If you only just granted it, wait -- Google allows up to 48 hours to propagate -- and press Verify again.
Verify: Notifications arriving ✗Play has never sent us anything for this package.Play Console → Monetisation setup: is the topic pasted exactly as the Revenue tab shows it, and did Send test notification report success? A *Failed to send* there is always the topic name, never us.
Verify: already connected to another workspaceThis package name is verified on a different ROAS Sensor account.One package has one owner. If that is also you, verify from that workspace; if not, contact us.
Both checks pass, purchases still absentThe sales are not reaching Play at all, or the app is not tagging them.A purchase through your own gateway (UPI, a web checkout) never touches Play Billing, so Play never notifies anyone -- report those from your server instead. If sales appear with no campaign, the app is not setting obfuscatedAccountId.
It worked, then stoppedAlmost always the Play Console grant was removed, or the app's package name changed here.Press Verify: it will name whichever half broke.

Anything Play sent while a step above was wrong is not lost. Notifications that arrive before verification are held and booked when Verify passes; after that, a failed delivery is retried by Google for seven days.

When nothing books: your own project

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.