
We’ve written before about why app environments are still broken from a verification standpoint, and what we think platforms should require before letting new sellers in. Those posts diagnosed the problem. This one is the prescription.
If you run an app marketplace, sell your own app inventory, or operate a platform that doesn’t have an app store at all, there is a concrete set of things you can do, most of them cheap, none of them novel, that make your app inventory verifiable. Verifiable app inventory wins spend. Unverifiable inventory gets filtered, discounted, or blocked. What follows is the playbook we recommend, organized by who you are in the supply chain.
First, the foundation everyone builds on
Two IAB Tech Lab standards underpin everything here.
The first is the OTT/CTV Store Assigned App Identification Guidelines, which define what value should be used as the store ID on each platform, what to do when a platform has no app store, and how those IDs should flow through bid requests.
The second is the app-ads.txt specification, which describes a verification loop: the developer publishes a website URL in their app’s store metadata, hosts an app-ads.txt file on that site, and exposes both via standard HTML meta tags on the store listing. Sellers pass the store listing URL in bid requests. Verifiers crawl the store page to find the developer’s site, crawl the site to read the app-ads.txt file, and enforce authorization on the app inventory.
Every recommendation below exists to keep that loop unbroken. When any link in the chain fails the store page won’t load, the meta tags are missing, the developer URL points to a Google Doc, verification fails, and buyers have to guess. Buyers don’t like guessing.
If you run an app marketplace
Give every app a public, crawlable listing page
Every app in your marketplace needs its own dedicated, publicly accessible web listing page. Not behind a login. Not behind a paywall. Not behind a CAPTCHA. Verification crawlers use this page to discover app ownership and link it to authorized sellers. If the page doesn’t resolve, the app effectively doesn’t exist to the verification ecosystem.
Just as important: the URL must work exactly as it’s transmitted in the bid request. If a crawler has to strip a trailing slash or manually massage the URL to get the page to load, you’ve broken automated verification for every buyer downstream.
Don’t geofence your listings
Regional availability is a legitimate business reality; geofencing your store pages is a self-inflicted wound. If an app is only available in France, a verifier checking an impression from France still needs to load that listing, and the verifier’s crawler may not be in France.
The better pattern is Google Play’s, which supports gl (country) and hl (language) query parameters so a crawler anywhere in the world can view the localized page. Compare two real cases:
- Leboncoin on Apple’s App Store fails to load at the default URL and requires the /fr/ path – a verifier with no prior knowledge of the impression’s country can’t easily validate the listing.
- LINE Manga on Google Play behaves similarly at the default URL, but appending &gl=jp resolves it, because the store exposes region as a parameter.
If you must restrict default visibility by market, at minimum give crawlers a documented, parameter-based way to reach a regional version of the page.
Implement the IAB Tech Lab meta tags
Embed the standardized meta tags on every listing page, at minimum appstore:developer_url (pointing to the developer’s owned website, where their app-ads.txt lives) and appstore:bundle_id.
The bundle ID tag matters more than it looks. Consider Hulu on Roku: the store listing URL contains a long-form identifier (d8f548dedc…), but the bid stream identifies the app by its legacy bundle ID, 2285. Nothing in the store URL tells you that. The meta tag is the bridge that lets a verifier connect what they see in reporting to the page they’re crawling.
Publish the signals buyers actually use
Programmatic buyers judging inventory quality want more than an app name. Display, cleanly and on every listing: total downloads, average rating and rating count, age classification and parental advisories, a direct link to the app’s privacy policy, its category, and an accurate description. Google Play exposes all of this; it should be the standard, not the ceiling.
Tighten your intake policies
Two rules at onboarding prevent years of downstream mess. First, assign stable, unique, non-overlapping store IDs, avoid generic text strings and small integers that collide with other ecosystems. Second, when developers submit their developer URL, automatically reject free-hosting services, blog platforms, and shared cloud storage links. A developer URL on blogspot.com or docs.google.com carries no organizational identity, no ownership permanence, and can be abandoned or replaced in an afternoon.
If you sell your own app inventory
Host a real app-ads.txt, and keep it reachable
Your app-ads.txt file belongs at the root of the domain listed in your app store profile. If your developer URL is studiox.com, the file lives at https://studiox.com/app-ads.txt. Then keep it accessible: no CAPTCHAs, no geo-fenced web servers, no bot-blocking that catches verification crawlers. If a crawler can’t reach your file, your global ad revenue can simply stop.
And use real hosting infrastructure. A developer URL on a free blogging platform, a Linktree, or a public Google Doc signals “high risk” to every buyer who checks, and the same goes for your privacy policy, which is required if your app supports advertising.
Win the triple match
DSPs run cross-reference checks across three places your corporate domain appears: your app store developer_url, your corporate website, and the seller domain your SSPs list for you in their public sellers.json files. These should be identical. If your store page says one thing and your SSP account says another, you can fail automated verification without anyone ever telling you.
The blueprint is simple: set your developer URL to your official business root domain, host app-ads.txt there, confirm your SSP partners list that same domain in sellers.json, and verify your seller_type is listed strictly as PUBLISHER.
Pass identifiers with precision
The bid request should match what the store listing reflects, in the most specific format the ecosystem supports. The details differ by platform, and the failure modes are all ones we see constantly in real bid streams:
- Apple iOS/tvOS: Pass the numeric track ID (e.g., 886445756 for Tubi), never a custom string. iOS bundle IDs can collide with Amazon and Google naming conventions — com.adrise.tubitv doesn’t tell you which environment you’re in, but a track ID is always unique to iOS.
- Google Play: Pass the reverse-DNS package name, and don’t touch the casing. Bundles like io.cheelee.app are case sensitive; pipelines that lowercase bundles break resolution.
- Amazon: Both the reverse-DNS format (with its .amazon suffix) and the ASIN-style ID resolve. The most common mistake we see is sellers wrapping an Amazon bundle in a Google Play URL: play.google.com/store/apps/details?id=com.outfit7.mytalkingangelafree.amazon looks plausible and resolves nothing.
- Roku: The legacy bundle ID (Hulu’s 2285) cannot be used to construct a working store URL. channelstore.roku.com/details/2285 does not resolve; only the long-form identifier does. Fabricated bundles like “com.hulu.plus.roku” are wholly invalid.
Which leads to the general rule: populate app.storeurl in every bid request with a URL that actually resolves when visited, not one generated by concatenating a store URL fragment with a bundle ID. Better still, make the store url value unique to each country or region where the app is available, with the right regional parameters included, so there’s never a question of whether a crawler can find your listing.
If your platform has no app store
Plenty of CTV devices and legacy set-top boxes have no defined app store, and IAB Tech Lab’s guidance covers them too: use a store ID in the format appname.deviceplatform. For example, com.nbcu.peacock.x1 for Peacock on X1.
That format alone doesn’t get you anywhere near the granularity of a real marketplace, though. Platforms distributing such app inventory should collect a small dossier from each seller: the app ID (built per the format above), the developer/app-ads.txt URL (which should match 1:1 with the seller domain in SSP sellers.json files for direct accounts), a privacy policy URL, an app category, and supported countries in ISO-3166-1-alpha-2 format.
That dossier is enough to run real verification. Take a hypothetical Tubi application to sell Comcast set-top-box inventory under com.tubitv.comcast, declaring tubitv.com as its developer URL. A bid request arrives citing a Pubmatic account. The check: does that account appear in the app-ads.txt file at tubitv.com? Does pubmatic.com/sellers.json list tubitv.com as the seller domain for the account, with a PUBLISHER seller type? Is the user in a declared supported country? Three lookups, and the app inventory is either authorized or it isn’t, no app store required. (Reseller and inventory-partner arrangements can be validated too; just follow the existing app-ads.txt spec’s rules for those declarations.)
The common thread
None of this is exotic. Every recommendation above amounts to the same thing: make the chain from impression to accountable business entity crawlable, consistent, and boring. The sellers and platforms that do this don’t just pass verification, they remove every excuse a buyer has to route spend elsewhere.
DeepSee.io now surfaces app-level compliance signals for mobile and CTV apps, including app-ads.txt status, developer URL trust, and privacy policy infrastructure using the same signal structure we’ve long applied on the web. If you want to see how your app inventory (or your marketplace’s inventory) measures up against these practices, get in touch.