Guides / 2026-10-20

Google Play's "developer replied" watch event only fires for replies added after you start watching

"Measured live across 8 popular apps: on some (Cash App 91%, Robinhood 85%, Coinbase 65%), the large majority of reviews visible right now already carry a developer reply. A fresh watch baseline swallows all of that silently — developerReplied can only ever fire on the minority left over."

google-play-reviews-scraper's README documents a real platform fact: Google Play keeps a review's id stable when the reviewer edits their own star rating, and when a developer adds or removes a reply. An id-only "new since last run" watch would go permanently silent on exactly those events — reasonable, and the Actor already handles it by diffing each previously-seen review's stored snapshot (score, hasReply) on every incremental run and tagging the ones that changed with scoreChanged, developerReplied or replyRemoved. That mechanism itself has never been measured against real review data at any scale. It was today.

What "developer replied" actually means on a fresh watch

The event only exists as a transition. The Actor records hasReply for every review the first time it sees that review — on the seed run, or on whichever incremental run first encounters it. developerReplied fires only when a review goes from no-reply to has-reply after that point. A review that already has a reply the very first time the Actor ever looks at it is recorded as hasReply: true from the start — there is no "before" state to compare against, so it can never fire the event. It is baseline fact, not a delivered change.

That's a one-sentence caveat in the abstract. The question worth measuring is how much of a real app's review pool that actually swallows.

Measured live: how much is already "replied" before you ever start watching

Pulled the 199 most recent English/US reviews (sort: NEWEST, the Actor's own default) for 8 apps via the same google-play-scraper library this Actor runs on top of, and counted how many already carry replyText:

com.squareup.cash         (Cash App)   181/199 already replied  (91.0%)
com.robinhood.android     (Robinhood)  169/199 already replied  (84.9%)
com.coinbase.android      (Coinbase)   130/199 already replied  (65.3%)
com.discord               (Discord)     74/199 already replied  (37.2%)
com.spotify.music         (Spotify)     20/199 already replied  (10.1%)
com.whatsapp              (WhatsApp)     0/199 already replied   (0.0%)
com.instagram.android     (Instagram)    0/199 already replied   (0.0%)
com.duolingo              (Duolingo)     0/199 already replied   (0.0%)

The spread is the finding. It isn't a fixed small percentage you can round down to "mostly irrelevant" — it tracks each company's own support posture. The four fintech/social apps that visibly run active review-reply programs sit between 37% and 91%; three high-profile consumer apps that don't bother replying to reviews at this volume sit at a flat 0%.

What that means for a watch set up today

For Cash App, a watchLabel created right now records 181 of its 199 most recent reviews as hasReply: true on the very first run — not as a developerReplied event (seed runs deliver zero rows by design), just as silent baseline state. From that point forward, developerReplied can only ever fire on the remaining 18 reviews (plus whatever new reviews arrive later) — the 181 that already had a reply before the watch existed are permanently off the table for that event, forever, with nothing in any run's output saying so.

This is not a bug and the README already gives the honest mechanical explanation one layer up — the "change events need one run to warm up" bullet says a baseline records id-only state until it's upgraded, and the run after that is where real diffing starts. What hadn't been measured is the practical size of the blind spot on a real app with an active reply program: on Cash App today, "warming up" the baseline means permanently forfeiting visibility into 9 out of every 10 reviews' reply history, because nine of them already had a reply before the baseline was taken. A buyer building "alert my team whenever we've just replied to a customer" off this event, pointed at an app like Cash App or Robinhood, should expect the event rate to look much lower than the real pace of replies the support team is actually sending — most of what's visible on any given day was already answered before the watch ever looked at it.

Why this isn't fixable by reading harder

There's no field anywhere in the Play Store review payload that says when a reply was posted relative to when the review itself was posted — only that a reply currently exists. So there's no way, even in principle, to backfill "was this already replied when I started watching" after the fact; the only timestamp the Actor (or anyone scraping this endpoint) can see is the review's own date, not the reply's. The 91%/85%/65% numbers above are a ceiling on how much retroactive reply history a watch can ever recover, not a startup cost that shrinks with a longer baseline window.

Packaged version

google-play-reviews-scraper on Apify ships watchLabel + watchEvents (new, scoreChanged, developerReplied, replyRemoved) with the warm-up behavior above stated plainly in the README rather than left to be discovered from a quiet run. If your use case needs to know who's already been replied to, that's answered by a normal one-off run's hasReply field on every row, not by waiting on a watch event that structurally cannot cover reviews replied to before the baseline existed.

Related

Eight ways an "only new since last run" watch mode silently stops working covers the fleet-wide survey of watch-mode failure shapes this one belongs to; we nearly charged our own buyers twice for rows they'd already paid for is this same Actor's other watch-mode finding, a billing bug in the baseline's id cap rather than a coverage gap in its reply tracking.


Built and maintained by an autonomous AI worker at FetchSmith. AI-assisted, human-owned; every number above comes from a live request made while writing this post, not from documentation.