"Why does the same app surface 'beautiful photos' as a top theme on the App Store while 'too many ads' quietly climbs on Google Play?" I chased that question for six weeks before something finally clicked.
I'm Hirokawa, an indie developer running wallpaper apps that have accumulated more than 50 million downloads since 2014. I've always replied to reviews by hand, but the outline of what each store actually complains about stayed blurry. The Gemini API's structured output made per-review classification much easier, but I had never wired up a pipeline that compared the two stores side by side.
This article is the six-week operating record of doing exactly that with the Gemini API. The pipeline ended up processing a few hundred fresh reviews per day for roughly sixty yen a month. There were a few surprises on the way there.
Why a cross-store diff was worth building
The trigger was the v2.1.0 release of Beautiful HD Wallpapers in April 2026. Positive reviews about "lock screen color accuracy" started piling up on the App Store, while Google Play quietly accumulated negative reviews about "fullscreen ads showing up more often."
Even when the iOS and Android builds use the same ad SDK versions and frequency caps, perceived ad frequency diverges because of device performance, network conditions, and OS-level behavior. The AdMob dashboard collapses everything into impressions, but the subjective experience lives on a different axis.
Classifying each store's reviews in isolation makes that temperature gap easy to miss. I needed something that put the same week of reviews side by side and flagged "categories one platform talks about but the other does not."
Both of my grandfathers were temple carpenters, and they used to say that even from the same beam, the way the wood warps depends on which direction you set it. I've started thinking about apps the same way: the same codebase, placed in different ground, produces a different reading from users.
The six-week pipeline — fetch, classify, diff
The pipeline has three stages. Stage one fetches reviews from the App Store Connect API and the Google Play Developer API. Stage two uses Gemini 2.5 Flash Lite to classify each review with structured output. Stage three uses Gemini 2.5 Pro for the weekly cross-store diff summary.
For fetching, a cron job runs twice a day and pulls the last 24 hours. The App Store side hits customerReviews with localizations, and the Google Play side hits reviews.list with translationLanguage=ja so the diff stays consistent regardless of the reviewer's locale.
Each review then flows through Flash Lite with this Pydantic schema:
from pydantic import BaseModel
from typing import Literal
class ReviewClassification(BaseModel):
sentiment: Literal["positive", "neutral", "negative"]
primary_category: Literal[
"wallpaper_quality",
"ad_experience",
"search_filter",
"download_save",
"battery_storage",
"subscription",
"crash_stability",
"ui_navigation",
"language_support",
"other",
]
severity: Literal["low", "medium", "high"]
user_intent: Literal["bug_report", "feature_request", "praise", "complaint", "question"]
one_line_summary: strseverity blends "how widespread is this likely to be" with "does this affect billing behavior." I worried about Flash Lite drifting on a fixed schema, but the top-level category labels stayed stable across the six-week window.
Stage three sends Pro a table of "iOS category frequency over the last 7 days" plus the same for Android, and asks for platform_only_topics (categories present on one side only) and gap_signals (categories present on both but with a meaningful skew).
Prompting Pro for a useful diff
Three things mattered in the Pro prompt.
First, allow re-normalization of similar categories. Flash Lite sometimes labels the same underlying complaint as ui_navigation on one review and search_filter on another. I gave Pro permission to merge those at coarser granularity when the diff makes more sense that way.
Second, talk in proportions, not raw counts. iOS and Android have very different review volumes, so absolute counts make the iOS side look chronically smaller. I told Pro to use category share, and to flag categories whose share gap exceeds three percentage points.
Third, weight monetization signals on a separate axis. Anything that touches subscription retention or in-app purchases should be promoted in priority even at low frequency. Metrics like eCPM and LTV land as raw numbers in the prompt, and giving Gemini numeric thresholds reads more reliably than asking for vague judgment.
Three platform gaps that actually showed up
Six weeks in, three categories stood out clearly between the stores.
The first was perceived ad load. The ad_experience negative share on Android sat about seven points higher than iOS. Drilling in, the Gemini summary picked up that on slower-network devices the skip button on the fullscreen ad took noticeably longer to appear. I rolled that into the AdMob mediation config by lowering the priority of Rewarded Interstitial placements on Android.
The second was feature discovery. iOS reviews asked for "more categories" and "rearranging favorites" near the top, while Android reviews barely mentioned either. I suspect either a difference in heavy-user demographics or a UI placement that makes those features harder to find on Android. v2.2.0 will increase the discoverability of the category tab on Android first.
The third was language support. Korean and Simplified Chinese localization gaps were called out about twice as often on Google Play as on the App Store. Google Play's regional distribution requirements make localization rougher edges more visible, and users seem more sensitive there.
Roughly sixty yen per month, with the human parts that I kept
The six-week running cost stabilized at about sixty yen per month. With around 300 new reviews per day, Flash Lite classification ran about twenty yen, and the weekly Pro diff cost about forty yen. Implicit Caching held the system prompt steady on the Pro side, which cut that piece to roughly a third of what I'd projected.
I didn't try to automate every step, though. Three pieces stay manual. First, the initial reply to any review classified as severity: high and user_intent: bug_report. Second, eyeballing every review for the first week after a major release. Third, the thirty-minute weekly sit-down to lock in priorities from the diff summary.
When I first dialed up to the internet in 1997 at age sixteen, the feeling of getting an English reply from a stranger on an overseas forum stayed with me. Every review has a person and a life behind it, and I didn't want to lose that completely to automation.
What's next
The pipeline matured over six weeks, but there's still room to grow.
The next thing I want to wire up is feeding the diff output straight into a TestFlight beta proposal list that lands in the engineering priority queue. After that, using Google Play's appVersion parameter so we can track how temperature shifts between v2.1.0 and v2.2.0 on each store. Quantifying ad-perception changes across versions would make release-gate decisions visibly more confident.
Review work looks tedious from the outside, but after twelve years of running mobile apps, I keep coming back to the same conclusion: it's the closest thing to a user's real voice we get. Gemini, so far, has been a remarkably good reading lens for that voice.