<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maxim Kosterin</title>
    <description>The latest articles on DEV Community by Maxim Kosterin (@maximstone).</description>
    <link>https://dev.to/maximstone</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F637997%2F5c59f658-0c12-4bb4-bbfc-cee71c560cfc.jpeg</url>
      <title>DEV Community: Maxim Kosterin</title>
      <link>https://dev.to/maximstone</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maximstone"/>
    <language>en</language>
    <item>
      <title>What it really takes to publish a browser extension</title>
      <dc:creator>Maxim Kosterin</dc:creator>
      <pubDate>Sun, 06 Sep 2026 14:49:57 +0000</pubDate>
      <link>https://dev.to/maximstone/what-it-really-takes-to-publish-a-browser-extension-jmo</link>
      <guid>https://dev.to/maximstone/what-it-really-takes-to-publish-a-browser-extension-jmo</guid>
      <description>&lt;p&gt;Every tutorial sells you the same fantasy. A weekend, a manifest.json, a popup — and you publish a Chrome extension with a neat little "published" badge. The coding part of that story is roughly true. Everything after the last commit is where the fantasy quietly dies.&lt;/p&gt;

&lt;p&gt;In 2026 there's a wrinkle: if you're one of the developers working with LLM agents, even the "after the last commit" part has shrunk. An agent drafts your store copy, localizes it into forty locales, and produces a first-draft privacy policy in an afternoon. What it can't do is wait in the queue for you — or answer to a reviewer for artifacts it generated on your behalf.&lt;/p&gt;

&lt;p&gt;That's the part where your extension actually becomes available to users. I've watched enough extensions go through store review to say it plainly: publishing is not one step.&lt;/p&gt;

&lt;p&gt;It's a gauntlet. Three gates, a queue, a reviewer, and a clock that restarts every time you get something wrong. Here's what that gauntlet looks like in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scale you're lining up behind
&lt;/h2&gt;

&lt;p&gt;First, some perspective on the queue you're joining. According to Chrome-Stats, which tracks the store continuously, the Chrome Web Store held roughly &lt;strong&gt;303,800 extensions&lt;/strong&gt; as of August 2026. Mozilla's directory counts over &lt;strong&gt;74,000 Firefox add-ons&lt;/strong&gt; as of January 2026, and community trackers put the Microsoft Edge add-ons catalog at around &lt;strong&gt;31,000&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Store&lt;/th&gt;
&lt;th&gt;Extensions tracked, mid-2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chrome Web Store&lt;/td&gt;
&lt;td&gt;~303,800&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox (AMO)&lt;/td&gt;
&lt;td&gt;74,000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Edge&lt;/td&gt;
&lt;td&gt;~31,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Sources: Chrome-Stats (Aug 2026), Wikipedia (Jan 2026), r/chrome_extensions cross-store tracker.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One tracker on r/chrome_extensions counted 49,518 &lt;em&gt;new&lt;/em&gt; Chrome extensions in a single quarter — more than the entire Edge catalog. Your extension isn't entering a curated gallery. It's entering a queue that gets longer every week, and it's being judged by systems built to cope with that flood.&lt;/p&gt;

&lt;p&gt;That flood has a new tributary: agent-assisted development has collapsed the cost of producing a working extension to an afternoon, and the queue is filling accordingly. Your extension isn't just competing with 303,800 existing ones — it's competing with everything else agents shipped this week.&lt;/p&gt;

&lt;h2&gt;
  
  
  The production before the upload
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F15m2w4cvvn39xs3mt1ra.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F15m2w4cvvn39xs3mt1ra.webp" alt="Scattered production materials — icons, screenshots, privacy policy, localization sheets — laid out before a single upload button" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what tutorials skip entirely: the upload button is not the first step. It's step thirty.&lt;/p&gt;

&lt;p&gt;Before you can even open the developer dashboard, you need to produce a small media production. Four icon sizes (16, 32, 48, 128 pixels for Chrome, a slightly different set for Firefox and Edge). At least one screenshot per store at a minimum of 1280×800 or 1280×720, though the stores recommend more. Chrome asks for promotional tiles — a 440×280 small promo, a 920×680 marquee, and a 1400×560 large marquee — if you ever want to be featured.&lt;/p&gt;

&lt;p&gt;Then the copy. A short description (132 characters for Chrome, 250 for Firefox). A detailed description in markdown, ideally with keywords researched against what your competitors rank for. A privacy policy URL that actually matches what your extension does, not a generic template that says "we collect nothing" while your analytics SDK quietly collects everything. A homepage URL. A support URL. A support email.&lt;/p&gt;

&lt;p&gt;If you're serious about distribution, you need that copy in more than one language. Chrome Web Store supports 40+ locales, and localized listings convert dramatically better than English-only ones. That's 40 translations of your short description, your detailed description, your changelog, and your screenshots with localized UI.&lt;/p&gt;

&lt;p&gt;Then the smaller decisions that turn out to matter. A category selection that determines which browsing surfaces surface your extension. A data declaration that lists every piece of user data you collect — Chrome's privacy disclosure form is not optional, and it must match your privacy policy. An onboarding flow that actually teaches new users what your extension does, because the store listing is marketing, not documentation.&lt;/p&gt;

&lt;p&gt;"A week of work" is the by-hand estimate — conservative, and accurate. If you're running an LLM agent, generation is the cheap part: store copy, forty locales, a landing page, a first-draft privacy policy, an afternoon. What doesn't shrink is verification. Every generated artifact has to be checked against what your extension actually does, because the store will check it against what your extension actually does — and a plausible privacy policy that doesn't match your analytics SDK is a rejection with better grammar. The week doesn't disappear; it converts from production into review. And all of it happens &lt;em&gt;before&lt;/em&gt; you touch the upload button, before the review queue, before the part where you wait.&lt;/p&gt;

&lt;p&gt;This is also the part where most developers cut corners — and where the tools that exist specifically for this job earn their keep. The &lt;a href="https://dojo.extenshi.io/tools/icon-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;icon generator&lt;/a&gt; produces a full store-ready icon set from a prompt or an SVG, plus a promo tile and a paste-ready manifest snippet (2 free AI generations, then credit packs for volume). The &lt;a href="https://dojo.extenshi.io/tools/seo-optimizer?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;SEO optimizer&lt;/a&gt; scores your listing copy against top competitors in your niche and suggests keyword, readability, and field-length fixes. The &lt;a href="https://dojo.extenshi.io/tools/ai-visibility?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;AI visibility tool&lt;/a&gt; does the same for AI assistants — scores your copy for discoverability by ChatGPT and Claude, then generates &lt;code&gt;llms.txt&lt;/code&gt; and Schema.org JSON-LD for your extension's site. The &lt;a href="https://dojo.extenshi.io/tools/page-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;page generator&lt;/a&gt; builds a polished single-page HTML landing site you can deploy anywhere.&lt;/p&gt;

&lt;p&gt;And if you already have an agent writing your copy, generation isn't your bottleneck — grounding is. A blank-prompt agent will happily produce a generic listing; what it can't do is know that the marquee tile is exactly 920×680, that Edge's priority queue has favored certain categories since February 2025, or which keywords the current top three in your niche actually rank on. Policy-grounded tools are what keep generated output from being confidently wrong.&lt;/p&gt;

&lt;p&gt;None of it requires a website of your own, either — which is the part tutorials &lt;em&gt;really&lt;/em&gt; skip. The moment your extension needs a privacy policy URL, a support URL, and a homepage, you're suddenly standing up infrastructure for a product that isn't launched. It doesn't have to work that way anymore: every page these tools can produce — privacy policy, pin guide, install instructions, welcome page, uninstall survey — can be hosted for you at a stable permalink. No domain to buy before you have users, no form to build, no server to run. A GitHub Pages account is no longer part of the minimum viable launch.&lt;/p&gt;

&lt;p&gt;None of this is glamorous. None of it is optional. And none of it is what the "publish a Chrome extension in 10 minutes" tutorial mentioned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate one: the manifest is not just config
&lt;/h2&gt;

&lt;p&gt;The first hidden stage happens before you upload anything. The manifest is where most future rejections are already baked in.&lt;/p&gt;

&lt;p&gt;Request &lt;a href="https://blog.extenshi.io/posts/host-permissions-all-urls-explained/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt;&lt;/a&gt; or the &lt;code&gt;tabs&lt;/code&gt; permission when you don't strictly need them and you've done two things at once. You've made every potential user's install dialog scarier, and you've flagged your submission for closer inspection.&lt;/p&gt;

&lt;p&gt;Google's own review documentation lists "dangerous permission requests" among the signals that make a reviewer examine an extension more closely. Being a new developer, shipping a new extension, and making significant code changes are on that list too. All four describe you on day one.&lt;/p&gt;

&lt;p&gt;Then there's the Manifest V3 deadline pressure. MV2 support is already gone from mainstream Chrome — we covered what the &lt;a href="https://blog.extenshi.io/posts/chrome-150-mv2-removal/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;Chrome 150 MV2 removal&lt;/a&gt; means for holdouts — and remote code execution (loading JavaScript from a server, &lt;code&gt;eval()&lt;/code&gt; on fetched strings) is banned outright in MV3. The rework itself is the tax: blocking &lt;code&gt;webRequest&lt;/code&gt; becomes declarativeNetRequest rules, and the persistent background page becomes a service worker that Chrome terminates whenever it idles — in-flight state dies with it, and anything that needs DOM access moves into an offscreen document. Ad-blocker authors fought the first change for years; everyone else meets the second one as a bug report. Plenty of developers discover the rules themselves from a rejection email rather than from the docs.&lt;/p&gt;

&lt;p&gt;And one codebase does not mean one package. Firefox wants &lt;code&gt;browser_specific_settings&lt;/code&gt; with an add-on ID, requires signing even for self-distribution, and its validator will flag things Chrome's tooling never mentions. And AMO's reviewers must be able to read your code: ship minified or bundled output — webpack, TypeScript, anything with a build step — and you're required to attach the readable source and build instructions, or the submission stalls. Edge mostly accepts the Chrome flavor but runs its own certification against its own developer policies. The "write once" promise quietly becomes "package three times."&lt;/p&gt;

&lt;p&gt;For agent-assisted development, this gate cuts both ways. An agent will refactor MV2 to MV3, minimize your permission set, and produce all three store packages in hours instead of days. It will also, if you let it, reach for &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; — host matching is tedious, and broad permissions always work. Agents optimize for making things run; reviewers optimize for why you needed that to run. Read the manifest diff like it's production code, because to a reviewer it is.&lt;/p&gt;

&lt;p&gt;This is the point where a five-minute sanity check beats a five-day review queue. The free &lt;a href="https://dojo.extenshi.io/tools/manifest-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;manifest generator&lt;/a&gt; builds and validates a cross-browser MV3 manifest with live store-policy checks, right in the browser, no sign-up — so the permission set that reaches the store has already survived a policy pass before you uploaded anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate two: what the review actually does
&lt;/h2&gt;

&lt;p&gt;All three stores combine automated scanning with human review, but the mix and the pace differ.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chrome Web Store.&lt;/strong&gt; Google combines manual and automated review. Every submission goes through the same pipeline, whatever your tenure as a developer. Officially, "for most extensions, review is completed within a few days, but it can take up to a few weeks." If your item sits in pending review for more than three weeks, Google asks you to contact developer support. That tells you something about what "a few weeks" has become in practice.&lt;/p&gt;

&lt;p&gt;The historical baseline has drifted. In early 2021, Google reported that most submissions finished review in under 24 hours, and over 90% within three days.&lt;/p&gt;

&lt;p&gt;In 2026, a PSA thread on the chromium-extensions developer forum reports review times growing under submission volume. One developer there described a minor update stuck in review since April 2026. Previous versions of the same extension had been approved within a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firefox AMO.&lt;/strong&gt; Mozilla runs two distinct passes. First, an automated validator at upload time: errors block the submission outright, and Mozilla's own guidance warns that security and privacy warnings can fail review later. Then human review, for listed distribution.&lt;/p&gt;

&lt;p&gt;Officially, signing and publishing can take up to 24 hours "or longer if your submission is selected for manual review." The community reading is blunter. On Mozilla's developer forum, the standard estimate for a manual review in 2026 is between one and two weeks. Backlog threads describe listed versions pending since November 2025. There's also a trap: AMO won't accept a new upload while an earlier version sits in the queue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Microsoft Edge.&lt;/strong&gt; Certification officially takes up to seven business days, for new submissions and updates alike. In Edge's own GitHub discussions, the developer support team puts typical review at five to seven business days.&lt;/p&gt;

&lt;p&gt;A criteria-driven priority queue introduced in February 2025 accelerates only selected extensions. First-time submissions also sit behind developer account verification. Microsoft says that can take from a few days to a few weeks.&lt;/p&gt;

&lt;p&gt;The honest summary table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Store&lt;/th&gt;
&lt;th&gt;Official guidance&lt;/th&gt;
&lt;th&gt;Community-reported reality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chrome Web Store&lt;/td&gt;
&lt;td&gt;A few days, up to a few weeks; contact support after 3&lt;/td&gt;
&lt;td&gt;Hours for trivial updates, 2–7 days typical for first submissions, weeks when flagged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox (listed)&lt;/td&gt;
&lt;td&gt;Up to 24 h unless selected for manual review&lt;/td&gt;
&lt;td&gt;1–2 weeks for manual review; backlog cases 6+ weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Edge&lt;/td&gt;
&lt;td&gt;Up to 7 business days&lt;/td&gt;
&lt;td&gt;~3 working days typical; 5–7 per support; account verification adds days&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of this is an SLA. Every number is "up to," and every clock includes weekends, queue depth, and the reviewer's judgment about whether your extension deserves a second look.&lt;/p&gt;

&lt;p&gt;Notice what's missing from this section: anything an agent can do for you. This is the one number in this post that agent-assisted development does not compress — which has a strategic consequence. When production shrinks to days, the queue becomes almost all of your calendar time, and avoiding a single rejection cycle becomes the highest-leverage optimization in the entire launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate three: rejection restarts everything
&lt;/h2&gt;

&lt;p&gt;Here's the part tutorials skip: a rejection isn't a fine, it's a reset. You fix the problem, resubmit, and go to the back of the queue — and Google's documentation notes explicitly that review times may be longer after an extension has been rejected or warned.&lt;/p&gt;

&lt;p&gt;Google's troubleshooting documentation maps what actually gets extensions rejected. The common reasons are almost embarrassingly preventable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Packaging errors.&lt;/strong&gt; Files referenced in the manifest that aren't in the package — most commonly missing images — or wrong paths. The extension fails before a human forms an opinion about it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functionality that doesn't match the listing.&lt;/strong&gt; If your backend is down at the moment of review, or a promised feature actually just links out to an external service, that's a rejection under "functionality not working" and "minimum functionality."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-purpose violations.&lt;/strong&gt; An extension must have one narrow purpose. Bundling product reviews with ad injection, or a toolbar with five unrelated services, gets split-or-reject treatment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clickbait metadata.&lt;/strong&gt; Descriptions designed to attract attention rather than describe the extension.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing privacy policy.&lt;/strong&gt; If your product handles any user data, you must post an accurate, current privacy policy disclosing how data is collected, used, and shared — in the designated dashboard field — and transmit it securely. This one bites developers who genuinely collect nothing but wire up an analytics SDK that does.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of the official list, the community lore adds two classics: leftover files from an MV2 past (a stray &lt;code&gt;background.html&lt;/code&gt; that MV3 service workers never use), and requesting permissions you don't need, which Google's support channels internally flag as a category of its own.&lt;/p&gt;

&lt;p&gt;Two of these have an agent-shaped variant in 2026. "Functionality not working" now includes the agentic overclaim: a listing (agent-written) that promises a feature the code (also agent-written) doesn't quite implement. "Missing privacy policy" increasingly means a &lt;em&gt;generated&lt;/em&gt; one — fluent, well-structured, and describing a data-minimal extension that doesn't match the analytics SDK someone wired in. The fix is the same in both cases: derive the listing and the policy from the code, not from a prompt. Have your agent read your manifest and network calls first, then write.&lt;/p&gt;

&lt;p&gt;And a rejection is not the worst outcome in the stack. The sharper edge is enforcement: extensions get taken down and accounts get suspended by automated systems, with a canned email citing "malware policy" and an appeal process that historically returned a template denial or weeks of silence. Google introduced a dedicated appeals flow in April 2026 — an Appeal button in the developer dashboard for item takedowns and account suspensions alike, with account issues handled first — which fixed the path but not the asymmetry: a reviewer's judgment takes days; an appeal's can take weeks.&lt;/p&gt;

&lt;p&gt;Every one of those is catchable before upload. That's exactly the job of a pre-publish scan: &lt;a href="https://docs.extenshi.io/developers/cli?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;&lt;code&gt;npx @extenshi/cli&lt;/code&gt;&lt;/a&gt; runs a security and policy scan from your terminal. It's 5 scans and 25 reads a month free, with prepaid &lt;a href="https://dojo.extenshi.io/billing?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;credit packs&lt;/a&gt; past that if you ship often. Five minutes of scanning is cheap insurance against a week in the queue ending in a packaging error — and the findings are machine-readable, so if an agent builds your extension, you don't even spend the five minutes: point the agent at the scanner and let it iterate until the list comes back empty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The onboarding gap
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install → active user: a typical drop-off shape&lt;/strong&gt; (an illustrative model, not a measured statistic)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install from store&lt;/strong&gt; — everyone who clicked "Add to browser".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find the icon&lt;/strong&gt; — most don't pin it and can't find it in the toolbar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First action&lt;/strong&gt; — no welcome page, no guidance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active user&lt;/strong&gt; — the rest uninstalled or forgot.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Approval is not adoption. This is the part where most developers declare victory and walk away — and then wonder why so few of those installs ever become active users.&lt;/p&gt;

&lt;p&gt;The store listing got them to click install. Nothing in the store listing taught them what to do next. Nothing told them to pin the extension to the toolbar so they can actually find it. Nothing showed them the first action to take, the first workflow to try, the first moment where the extension proves it's worth the permission dialog they just clicked through.&lt;/p&gt;

&lt;p&gt;That's the onboarding gap, and it's where the tools most developers never build are also the ones that matter most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A pin guide.&lt;/strong&gt; A single illustrated page showing users how to find your extension icon and pin it to the toolbar, with your own icon embedded. It's the one onboarding step that almost nobody ships, and the one that correlates most strongly with day-1 retention. The &lt;a href="https://dojo.extenshi.io/tools/instruction-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;pin guide generator&lt;/a&gt; builds this as a self-contained page you can host anywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install instructions.&lt;/strong&gt; Per-browser install steps — the store route for production users, the unpacked route for beta testers, what to try first. The &lt;a href="https://dojo.extenshi.io/tools/install-instructions?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;install instructions tool&lt;/a&gt; ships this as markdown or a standalone page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A welcome page.&lt;/strong&gt; The post-install page that opens automatically after someone installs your extension. It's your one shot at a first impression, and most developers leave it as the default empty page. The &lt;a href="https://dojo.extenshi.io/tools/onboarding-page?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;welcome page builder&lt;/a&gt; lets you compose one from illustration and text blocks, add click markers for key actions, and confirm that the install actually succeeded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uninstall feedback.&lt;/strong&gt; When someone removes your extension, Chrome lets you point &lt;code&gt;setUninstallURL()&lt;/code&gt; at one page. Most developers point it at their homepage. The &lt;a href="https://dojo.extenshi.io/tools/uninstall-feedback?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;uninstall feedback tool&lt;/a&gt; gives you a branded survey with structured churn reasons and version trends — hosted for you at a stable permalink, so the whole integration is one line of code and no backend, and you learn why you're losing users instead of guessing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is in the store review checklist. None of it affects whether you get approved. All of it affects whether the approval matters.&lt;/p&gt;

&lt;p&gt;With an agent, building these pages is an afternoon, which removes the last excuse: the onboarding gap in 2026 isn't a build gap, it's a measurement gap. The pages are cheap; knowing whether they work is not. That's the real argument for structured uninstall feedback over a homepage redirect — churn reasons collected as data are something you &lt;em&gt;and your agent&lt;/em&gt; can act on. "Bugs" tells you nothing; "stopped working on YouTube after the last update" is a backlog item.&lt;/p&gt;

&lt;h2&gt;
  
  
  After approval: the loop nobody budgets for
&lt;/h2&gt;

&lt;p&gt;Getting listed is not the finish line. It's the start of a maintenance loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every update re-enters review.&lt;/strong&gt; Google is explicit that new items and updates to existing ones go through the same review process. Your hotfix for a production bug waits in the same queue as everyone's first submission. Agent speed makes this worse before it makes it better: when shipping an update costs a prompt, it's tempting to ship ten. Each one spends a review cycle. Batch your changes and pay the queue once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three stores, three dashboards, three policies.&lt;/strong&gt; The Chrome listing, the AMO listing, and the Partner Center submission are separate objects that drift apart unless you keep them in sync. The &lt;a href="https://dojo.extenshi.io/tools/publish?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;publish tool&lt;/a&gt; ships one artifact to all three stores via CLI or MCP, straight from your machine — one command instead of three dashboard sessions. If you publish through an agent, that shape matters more than the convenience: agents can't click a dashboard, but they can call a CLI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deadlines keep moving.&lt;/strong&gt; The &lt;a href="https://blog.extenshi.io/posts/extension-pulse-2026-w35/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;Chrome Web Store API V1 shuts down on October 15, 2026&lt;/a&gt; — if your publish automation or analytics tooling still speaks V1, it stops speaking at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval is not survival.&lt;/strong&gt; The same tracker that counts quarterly launches found that of 124,342 extensions launched in the first half of 2026, only about 1.3% ever reached 1,000 users. The store listing is the beginning of distribution, not the end of it. Agent-assisted development moves the floor, not the ceiling: producing an extension is now trivial, getting it adopted is as hard as ever. When everyone can ship, shipping stops being the moat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running it is another hidden build.&lt;/strong&gt; Somewhere past approval, most developers discover the extension was the easy half of the product. Is anyone actually using it? Which features? What's crashing? Even "just add analytics" is extension-shaped: MV3 bans remote code, so the standard &lt;code&gt;gtag.js&lt;/code&gt; snippet is off the table, and the official path is GA4's Measurement Protocol — raw HTTP events sent from a service worker Chrome can kill mid-session. Add accounts, and you need somewhere for sessions to live. Make the extension paid, and you need a billing provider: Google shut Chrome Web Store Payments down — deprecated in 2020, gone by February 2021 — and there has been no store-native way to sell an extension since; every paid extension runs Stripe or Paddle on the side, with license keys, refunds, and taxes as the developer's problem. It's a second stack of decisions (analytics, crash reporting, auth, billing), and here's the part nobody warns you about — every service you wire in changes what your extension collects, which changes your privacy policy and your data declaration, which makes it a review event. An agent compresses the wiring but not the decisions: it can integrate any analytics SDK in an hour, but choosing what to collect, where it lives, and how it's disclosed is still yours — and a wrong choice here is a rejection that arrives &lt;em&gt;after&lt;/em&gt; you have users. The cheapest loop to close first is churn: the hosted uninstall survey is one line of code and returns structured reasons; real usage analytics can wait until you have usage to analyze.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last number is the one I'd pin above every desk. The gauntlet exists, it's worth walking through, and you should go in knowing that shipping is step one of a much longer job.&lt;/p&gt;

&lt;h2&gt;
  
  
  How long does it take to publish a Chrome extension, really?
&lt;/h2&gt;

&lt;p&gt;Add up the realistic path for a first-time, three-store launch, agent-assisted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Icons, screenshots, promo tiles, and store copy: an afternoon to generate with an agent, plus a day to verify — and real screenshots still need a real browser at real resolutions.&lt;/li&gt;
&lt;li&gt;Privacy policy, data declaration, and homepage: minutes to generate, but only trustworthy if derived from your actual permissions and network calls rather than a template.&lt;/li&gt;
&lt;li&gt;Permission and manifest design, including the MV3 rework: hours, with an agent iterating against a policy scanner.&lt;/li&gt;
&lt;li&gt;Cross-browser packaging and testing: hours — validators are exactly the kind of loop agents run well.&lt;/li&gt;
&lt;li&gt;Onboarding materials — pin guide, welcome page, install instructions: hours; with agents and hosted pages there is no longer an excuse to skip them.&lt;/li&gt;
&lt;li&gt;First review round across three queues: 1–2 weeks typical, with real risk of more.&lt;/li&gt;
&lt;li&gt;One rejection cycle, if it happens: add the full queue time again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The pattern in every failure mode above is the same: the developer found out about the problem &lt;em&gt;from the store, after the queue&lt;/em&gt;. Every tool worth using in this process exists to move that discovery earlier — before the upload, before the week of waiting, before the rejection email.&lt;/p&gt;

&lt;p&gt;That's the design goal behind the full set of developer tools. The &lt;a href="https://dojo.extenshi.io/tools/manifest-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;manifest generator&lt;/a&gt; catches permission and policy problems at design time. The &lt;a href="https://dojo.extenshi.io/tools/privacy-policy-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;privacy-policy generator&lt;/a&gt; turns your extension's real permissions into a GDPR/CWS/AMO-aligned policy instead of a blank page. The &lt;a href="https://dojo.extenshi.io/tools/icon-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;icon generator&lt;/a&gt; produces store-ready icon sets and promo tiles from a prompt. The &lt;a href="https://dojo.extenshi.io/tools/seo-optimizer?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;SEO optimizer&lt;/a&gt; and &lt;a href="https://dojo.extenshi.io/tools/ai-visibility?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;AI visibility tool&lt;/a&gt; score your listing copy against competitors and AI assistants. The &lt;a href="https://dojo.extenshi.io/tools/page-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;page generator&lt;/a&gt; builds a landing page. The &lt;a href="https://dojo.extenshi.io/tools/instruction-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;pin guide&lt;/a&gt;, &lt;a href="https://dojo.extenshi.io/tools/install-instructions?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;install instructions&lt;/a&gt;, &lt;a href="https://dojo.extenshi.io/tools/onboarding-page?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;welcome page&lt;/a&gt;, and &lt;a href="https://dojo.extenshi.io/tools/uninstall-feedback?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;uninstall feedback&lt;/a&gt; close the onboarding gap that turns installs into active users. The CLI scanner finds packaging, permission, and security rejection triggers before a reviewer does. The &lt;a href="https://dojo.extenshi.io/tools/publish?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;publish tool&lt;/a&gt; ships one artifact to all three stores from your terminal. When you &lt;a href="https://docs.extenshi.io/developers/claim-your-extension?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-2" rel="noopener noreferrer"&gt;claim your extension&lt;/a&gt; on the catalog, you also see it from the outside — the same view our scanners get. None of it assumes you have a website, a backend, or a domain: every page can be hosted for you, and the survey wires up with one line. The minimum footprint for a three-store launch is the extension itself.&lt;/p&gt;

&lt;p&gt;The queue is real, and no tool — and no agent — removes it. For agent-assisted developers, that inverts the old advice: once production compresses to days, the difference between a two-week launch and a two-month launch almost always &lt;em&gt;is&lt;/em&gt; the review — specifically, whether you entered the queue carrying a problem the queue was guaranteed to find. Every rejection costs a full queue you no longer have production work to hide behind. Clear the first submission, and what's left is the part that was always the real job: turning an approval into a user base.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Typical time (agent-assisted)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Production&lt;/td&gt;
&lt;td&gt;Icons, screenshots, copy, privacy policy, localization&lt;/td&gt;
&lt;td&gt;1–3 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gate 1 — manifest&lt;/td&gt;
&lt;td&gt;Manifest design, permission audit, MV3 compliance&lt;/td&gt;
&lt;td&gt;hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gate 2 — review queue&lt;/td&gt;
&lt;td&gt;Automated + manual review, 3 stores × 3 queues&lt;/td&gt;
&lt;td&gt;1–2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gate 3 — rejection?&lt;/td&gt;
&lt;td&gt;Fix → resubmit → back of the queue&lt;/td&gt;
&lt;td&gt;+1–2 weeks per cycle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval&lt;/td&gt;
&lt;td&gt;Listed in stores — not the finish line&lt;/td&gt;
&lt;td&gt;Day 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Onboarding&lt;/td&gt;
&lt;td&gt;Pin guide, welcome page, install instructions&lt;/td&gt;
&lt;td&gt;hours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Code complete to live in 3 stores: 2–6 weeks typical, almost all of it queue. Typical first-time, three-store path.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbszmq6arxak7a78r4yq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbszmq6arxak7a78r4yq7.png" alt="The publishing gauntlet in one picture: market size, what to prepare before the upload, the six stages, why submissions get rejected, and review times official vs reality" width="800" height="975"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The publishing gauntlet in one picture — what to prepare, the gates, rejection reasons, review times, and the queue that owns your calendar.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/webstore/review-process" rel="noopener noreferrer"&gt;"Chrome Web Store review process"&lt;/a&gt;, Google Chrome Developers (accessed 2026-08-27)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/webstore/troubleshooting" rel="noopener noreferrer"&gt;"Troubleshooting Chrome Web Store violations"&lt;/a&gt;, Google Chrome Developers (accessed 2026-08-27)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://extensionworkshop.com/documentation/publish/submitting-an-add-on/" rel="noopener noreferrer"&gt;"Submitting an add-on"&lt;/a&gt; and &lt;a href="https://extensionworkshop.com/documentation/publish/signing-and-distribution-overview/" rel="noopener noreferrer"&gt;"Signing and distribution overview"&lt;/a&gt;, Firefox Extension Workshop (accessed 2026-08-27)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/microsoft-edge/extensions/publish/publish-extension" rel="noopener noreferrer"&gt;"Publish a Microsoft Edge extension"&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/microsoft-edge/extensions/publish/add-ons-curation" rel="noopener noreferrer"&gt;"Curation and review process for extensions"&lt;/a&gt;, Microsoft Learn (accessed 2026-08-27)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blogs.windows.com/msedgedev/2025/02/26/empowering-microsoft-edge-add-ons-developers-with-faster-reviews/" rel="noopener noreferrer"&gt;"Empowering Microsoft Edge Add-ons developers with faster reviews"&lt;/a&gt;, Microsoft Edge Dev Blog, 2025-02-26&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://groups.google.com/a/chromium.org/g/chromium-extensions/c/VJ6DcpEn51Y/m/yuxvHWdwCAAJ" rel="noopener noreferrer"&gt;"PSA: Increase in review times for submissions to the Chrome Web Store"&lt;/a&gt;, chromium-extensions developer forum, 2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://discourse.mozilla.org/t/add-on-approval-time/146522" rel="noopener noreferrer"&gt;"Add-on Approval Time?"&lt;/a&gt; and &lt;a href="https://discourse.mozilla.org/t/listed-version-pending-review-since-3-july/149202" rel="noopener noreferrer"&gt;"Listed version pending review since 3 July"&lt;/a&gt;, Mozilla Add-ons Discourse, 2025–2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/microsoft/MicrosoftEdge-Extensions/discussions/46" rel="noopener noreferrer"&gt;"Why is Microsoft so slow in approving extensions?"&lt;/a&gt; discussion #46 and &lt;a href="https://github.com/microsoft/MicrosoftEdge-Extensions/discussions/114" rel="noopener noreferrer"&gt;"Long review process for extensions"&lt;/a&gt; discussion #114, MicrosoftEdge-Extensions, GitHub&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome-stats.com/chrome/stats" rel="noopener noreferrer"&gt;Chrome-Stats store statistics&lt;/a&gt;, August 2026 (Chrome Web Store totals)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Add-on_(Mozilla)" rel="noopener noreferrer"&gt;"Add-on (Mozilla)"&lt;/a&gt;, Wikipedia, January 2026 figure (Firefox add-on count)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/chrome_extensions/comments/1vdij5w/" rel="noopener noreferrer"&gt;"Chrome Web Store launch stats: how many new extensions reach 1K / 10K / 100K users"&lt;/a&gt;, r/chrome_extensions, 2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/extensions/develop/migrate" rel="noopener noreferrer"&gt;"Migrate to Manifest V3"&lt;/a&gt; and &lt;a href="https://developer.chrome.com/docs/extensions/how-to/integrate/google-analytics-4" rel="noopener noreferrer"&gt;"Integrate Google Analytics 4 with extensions (Measurement Protocol)"&lt;/a&gt;, Google Chrome Developers (accessed 2026-08-29)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://extensionworkshop.com/documentation/publish/source-code-submission/" rel="noopener noreferrer"&gt;"Source code submission"&lt;/a&gt; and &lt;a href="https://extensionworkshop.com/documentation/publish/add-on-policies/" rel="noopener noreferrer"&gt;"Add-on Policies"&lt;/a&gt;, Firefox Extension Workshop (accessed 2026-08-29)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/blog/cws-new-appeals-process" rel="noopener noreferrer"&gt;"CWS new appeals process"&lt;/a&gt;, Google Chrome Developers, 2026-04-08&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.eff.org/deeplinks/2021/12/googles-manifest-v3-still-hurts-privacy-security-innovation" rel="noopener noreferrer"&gt;"Google's Manifest V3 Still Hurts Privacy, Security, and Innovation"&lt;/a&gt;, Electronic Frontier Foundation, 2021-12&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.zdnet.com/article/google-deprecates-web-store-payments-api-effectively-nuking-chrome-paid-extensions/" rel="noopener noreferrer"&gt;"Google deprecates Web Store Payments API, effectively nuking Chrome paid extensions"&lt;/a&gt;, ZDNet, 2020-09&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://groups.google.com/a/chromium.org/g/chromium-extensions/c/IjxW_pcdEMc" rel="noopener noreferrer"&gt;"Chrome Webstore Account Suspended?"&lt;/a&gt; and &lt;a href="https://groups.google.com/a/chromium.org/g/chromium-extensions/c/kFY66qUKuUE" rel="noopener noreferrer"&gt;"Our extension was removed and dev account suspended"&lt;/a&gt;, chromium-extensions developer forum&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://palant.info/2018/07/03/google-to-developers-we-take-down-your-extension-because-we-can/" rel="noopener noreferrer"&gt;"Google to developers: we take down your extension because we can"&lt;/a&gt;, palant.info, 2018-07-03&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;p&gt;No Extenshi catalog data was used in this post. Store-size figures come from Chrome-Stats' continuous tracker (Chrome, Aug 2026), Wikipedia's summary of Mozilla's directory (Firefox, Jan 2026), and a community cross-store tracker cited on r/chrome_extensions (Edge). Review-timeline figures pair each store's official documentation with community-reported experiences on the vendors' own developer forums; where the two diverge, both are shown. The 1.3%-reaching-1,000-users figure comes from the r/chrome_extensions launch-stats analysis of extensions launched January–July 2026 and was not independently verified. The onboarding funnel is an illustrative model of a typical drop-off shape, not a measured statistic. The MV3 rework, appeals, payments, and analytics constraints cite Google's and Mozilla's official documentation and announcements; enforcement experiences additionally draw on developer reports in the chromium-extensions forum.&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Your Chrome extension needs a privacy policy. Here's one in 2 minutes.</title>
      <dc:creator>Maxim Kosterin</dc:creator>
      <pubDate>Thu, 09 Jul 2026 23:13:40 +0000</pubDate>
      <link>https://dev.to/maximstone/your-chrome-extension-needs-a-privacy-policy-heres-one-in-2-minutes-58bn</link>
      <guid>https://dev.to/maximstone/your-chrome-extension-needs-a-privacy-policy-heres-one-in-2-minutes-58bn</guid>
      <description>&lt;p&gt;You finished the extension. The listing is written, the screenshots look great, you hit &lt;strong&gt;Submit for review&lt;/strong&gt; - and a few days later the Chrome Web Store rejects it over something that has nothing to do with your code: the privacy policy.&lt;/p&gt;

&lt;p&gt;It's one of the most common non-code rejection reasons, it blocks Firefox and Edge submissions too, and it's entirely avoidable. This post covers when you actually need a policy, what reviewers look for, and two ways to produce one - by hand, or generated from your &lt;code&gt;manifest.json&lt;/code&gt; in about two minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do you actually need one?
&lt;/h2&gt;

&lt;p&gt;Shorter answer than you'd hope: &lt;strong&gt;almost certainly yes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Chrome Web Store requires a privacy policy whenever your extension collects or transmits &lt;em&gt;user data&lt;/em&gt;. The trigger is the actual data handling, not the mere presence of a permission in your manifest - but in practice these are the capabilities that usually mean you're collecting something:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;storage&lt;/code&gt; - if you persist data tied to a user (purely local, non-personal settings don't trigger the requirement on their own)&lt;/li&gt;
&lt;li&gt;host permissions (&lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt;, &lt;code&gt;*://*.example.com/*&lt;/code&gt;) - you &lt;em&gt;can&lt;/em&gt; read
personal page content, and reviewers treat broad host access as a strong signal that you need a policy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tabs&lt;/code&gt;, &lt;code&gt;history&lt;/code&gt;, &lt;code&gt;bookmarks&lt;/code&gt;, &lt;code&gt;cookies&lt;/code&gt; - browsing data&lt;/li&gt;
&lt;li&gt;any analytics, crash reporting, or error tracking (yes, self-hosted counts)&lt;/li&gt;
&lt;li&gt;accounts, sync, or anything that touches an email address&lt;/li&gt;
&lt;li&gt;data users type into the extension - form fields, notes, saved content, or messages are user data even when no permission appears in your manifest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of the policy URL itself, Chrome makes you fill out the &lt;strong&gt;privacy practices disclosure&lt;/strong&gt; in the Developer Dashboard - a per-item form where you declare what data you collect and certify compliance with the &lt;strong&gt;Limited Use&lt;/strong&gt; policy (purpose limitation, plus no selling, no advertising or data-broker transfer, and no human reading of the data outside a few narrow exceptions). Firefox no longer makes you host a privacy policy on AMO - that requirement was&lt;br&gt;
dropped in August 2025; you now declare data collection with the&lt;br&gt;
&lt;code&gt;browser_specific_settings.gecko.data_collection_permissions&lt;/code&gt; manifest key and Firefox shows users a built-in consent prompt (mandatory for new add-ons since November 2025, rolling out to all add-ons through 2026). Microsoft Edge Add-ons still asks for a privacy policy URL in Partner Center for anything handling personal information.&lt;/p&gt;

&lt;p&gt;So unless your extension requests no permissions and phones home to nothing, plan on shipping a policy with v1 - and plan for the rules getting stricter, not looser. From &lt;strong&gt;August 1, 2026&lt;/strong&gt;, the Chrome Web Store limits data collection to what's strictly necessary for your extension's single stated purpose, and requires that collection to be disclosed prominently &lt;em&gt;in the product itself&lt;/em&gt;, not only in the store listing.&lt;/p&gt;
&lt;h2&gt;
  
  
  What reviewers actually check
&lt;/h2&gt;

&lt;p&gt;A privacy policy for an extension isn't a legal essay - it's a short document that answers five questions without contradicting your listing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What do you collect?&lt;/strong&gt; Named concretely: "the text of the current tab", "the URLs you visit", "your email address", not "certain information".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why?&lt;/strong&gt; Each data point maps to a feature. Collecting without a stated purpose is what the Limited Use policy exists to kill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where does it go?&lt;/strong&gt; On-device only? Your server? Third parties (analytics, payment processors)? Name them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How long do you keep it, and how does someone get it deleted?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who do I email about this?&lt;/strong&gt; A working contact.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst6tc42dv1qfzzfkmlsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fst6tc42dv1qfzzfkmlsp.png" alt="Generated policy Markdown including the Chrome Web Store Limited Use commitment" width="546" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two structural requirements trip people up more than the content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The URL has to work.&lt;/strong&gt; A policy link that 404s, redirects to your homepage, or points at a Google Doc with restricted access is an instant rejection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It has to match your disclosure form.&lt;/strong&gt; If the privacy practices tab says "collects website content" and your policy says "we collect nothing", a human reviewer notices the contradiction.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The policy is necessary, but it isn't the whole requirement
&lt;/h2&gt;

&lt;p&gt;Here's the part most guides skip. If your extension collects any user data, the Chrome Web Store also wants a &lt;strong&gt;prominent disclosure and the user's affirmative consent inside the extension's own UI&lt;/strong&gt;, shown &lt;em&gt;before&lt;/em&gt; you collect anything - and it explicitly cannot live only in your privacy policy. In practice that's a first-run screen (or an options-page section) that names what you collect and why, with a control the user actively clicks to agree.&lt;/p&gt;

&lt;p&gt;So a complete answer is two things: a hosted policy (the rest of this article) &lt;em&gt;and&lt;/em&gt; an in-product consent step. The rule that ties them together: your policy, the privacy disclosures you fill in on the Developer Dashboard, and what your extension actually does must all say the same thing. Contradictions between them are treated as a policy violation and can take down every extension on the account, not just the one under review.&lt;/p&gt;
&lt;h2&gt;
  
  
  The manual route: a skeleton that passes
&lt;/h2&gt;

&lt;p&gt;If you'd rather write it yourself, this outline covers what the stores expect.&lt;br&gt;
Fill every section, delete nothing silently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Privacy Policy - &amp;lt;Extension Name&amp;gt;&lt;/span&gt;

&lt;span class="ge"&gt;_Last updated: &amp;lt;date&amp;gt;_&lt;/span&gt;

&lt;span class="gu"&gt;## What we collect&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;point&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; - used for &lt;span class="nt"&gt;&amp;lt;feature&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;point&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; - used for &lt;span class="nt"&gt;&amp;lt;feature&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## What we do NOT collect&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;the&lt;/span&gt; &lt;span class="na"&gt;reassuring&lt;/span&gt; &lt;span class="na"&gt;part&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt; &lt;span class="na"&gt;browsing&lt;/span&gt; &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;etc.&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;true&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Where your data is processed&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;on-device&lt;/span&gt; &lt;span class="err"&gt;/&lt;/span&gt; &lt;span class="na"&gt;our&lt;/span&gt; &lt;span class="na"&gt;servers&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;/&lt;/span&gt; &lt;span class="na"&gt;third&lt;/span&gt; &lt;span class="na"&gt;parties&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;named&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Data retention &amp;amp; deletion&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;how&lt;/span&gt; &lt;span class="na"&gt;long&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;and&lt;/span&gt; &lt;span class="na"&gt;how&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt; &lt;span class="na"&gt;requests&lt;/span&gt; &lt;span class="na"&gt;deletion&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Your rights&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;GDPR&lt;/span&gt; &lt;span class="na"&gt;basics&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;you&lt;/span&gt; &lt;span class="na"&gt;have&lt;/span&gt; &lt;span class="na"&gt;EU&lt;/span&gt; &lt;span class="na"&gt;users&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt; &lt;span class="na"&gt;which&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;on&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt; &lt;span class="na"&gt;global&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;you&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Contact&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;real&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Budget 30-60 minutes to do this honestly: the slow part isn't writing, it's auditing your own manifest and dependencies to figure out what you &lt;em&gt;actually&lt;/em&gt; collect. An extension with &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; and a fetch to your API collects more than most authors think.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2-minute route: generate it from your manifest
&lt;/h2&gt;

&lt;p&gt;The audit step is mechanical - your &lt;code&gt;manifest.json&lt;/code&gt; already declares most of what your extension can touch. That's the idea behind the &lt;a href="https://dojo.extenshi.io/privacy-policy-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-1" rel="noopener noreferrer"&gt;privacy policy generator&lt;/a&gt; we built at Extenshi. It's free and doesn't ask you to sign up - generation runs in your browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 - Select your permissions.&lt;/strong&gt; The same set as your manifest&lt;br&gt;
(&lt;code&gt;storage&lt;/code&gt;, host permissions, &lt;code&gt;tabs&lt;/code&gt;, &lt;code&gt;webRequest&lt;/code&gt;, ...). Each permission you toggle adds the matching, correctly-scoped data-practice language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 - Declare your data practices.&lt;/strong&gt; Extension name, contact email, whether you run analytics, accounts, or payments, and what users provide directly: form input, content they create, personal communications, health information. That last group is the one manifest-only tools miss - it has no permission to derive from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hj9ef8fmn77vn6gimd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hj9ef8fmn77vn6gimd3.png" alt="Declaring data users provide directly: form input, created content, communications, health" width="620" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 - Pick your legal coverage.&lt;/strong&gt; GDPR is on by default (store extensions are global, so EU users are a given), with CCPA/CPRA and child-directed (COPPA) toggles if they apply to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4twxsrw8jrvglx94nd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe4twxsrw8jrvglx94nd9.png" alt="Legal coverage toggles: GDPR, CCPA/CPRA, COPPA" width="600" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 - Export&lt;/strong&gt; as Markdown or HTML. The preview updates live, so you can read exactly what you're shipping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5vmut48544gnlfn15cj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp5vmut48544gnlfn15cj.png" alt="The generator: consent warning on top, permissions selected on the left, live policy preview on the right" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the sections are derived from your permissions and declared practices, the failure mode from the previous section - a policy that contradicts what the extension really does - mostly disappears. The tool also flags the part most people learn from a rejection email: it reminds you that the policy alone isn't enough and links the in-product disclosure-and-consent requirement covered above. If you're starting a new extension and want the same treatment for the manifest itself, there's a &lt;a href="https://dojo.extenshi.io/manifest-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-1" rel="noopener noreferrer"&gt;Manifest V3 generator&lt;/a&gt; that validates against store policies as you build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting the policy (the 5-minute part everyone forgets)
&lt;/h2&gt;

&lt;p&gt;The stores want a stable, public URL that doesn't require a sign-in. Google doesn't bless any specific host, so the bar is just that: reachable by anyone, and not going anywhere. Cheapest options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Pages&lt;/strong&gt; - drop the exported HTML into a repo, enable Pages, done. A &lt;code&gt;github.io&lt;/code&gt; URL is public and stable, which is all reviewers need.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A page on your existing site&lt;/strong&gt; - &lt;code&gt;/privacy&lt;/code&gt; next to your landing page.&lt;/li&gt;
&lt;li&gt;Avoid: Google Docs (access settings rot), Notion links behind "continue with Notion", URL shorteners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then wire it up in each store:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Store&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Chrome Web Store&lt;/td&gt;
&lt;td&gt;Developer Dashboard -&amp;gt; item -&amp;gt; &lt;strong&gt;Privacy&lt;/strong&gt; tab (paste the URL + fill the practices disclosure)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Firefox Add-ons&lt;/td&gt;
&lt;td&gt;Declare data collection via the &lt;code&gt;data_collection_permissions&lt;/code&gt; manifest key; hosting a policy URL is now optional (still recommended)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge Add-ons&lt;/td&gt;
&lt;td&gt;Partner Center -&amp;gt; extension property -&amp;gt; &lt;strong&gt;Privacy policy URL&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Rejection traps that survive a "valid" policy
&lt;/h2&gt;

&lt;p&gt;Seen in the wild, all of these pass a casual read and still get flagged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website policy, not extension policy.&lt;/strong&gt; You reused your SaaS privacy page; it talks about cookies and newsletters and never mentions the extension's permissions. Reviewers read it as missing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over-collection mismatch.&lt;/strong&gt; Manifest requests &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt;; policy says "we do not collect browsing data". One of those is wrong - either narrow the permission or fix the policy. (Narrow the permission. It also improves your install-prompt.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale after a feature.&lt;/strong&gt; You added an analytics SDK in v1.4 and the policy still reflects v1.0. Updates get re-reviewed too - this is a common way for a previously-approved extension to pick up a violation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy hosted inside the extension.&lt;/strong&gt; A &lt;code&gt;chrome-extension://&lt;/code&gt; URL or a page only reachable after install doesn't count. It must be a public web URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;A privacy policy is the cheapest rejection to prevent: one honest page, hosted anywhere public, consistent with your manifest and your disclosure form. Write it by hand with the skeleton above, or &lt;a href="https://dojo.extenshi.io/privacy-policy-generator?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-1" rel="noopener noreferrer"&gt;generate it from your permissions&lt;/a&gt; in a couple of minutes and spend the time you saved on the listing screenshots.&lt;/p&gt;

&lt;p&gt;The policy is one of several review axes, though. Risky permission combinations, vulnerable dependencies, and remote-code patterns get extensions rejected (and taken down) just as reliably - that side we cover with a &lt;a href="https://docs.extenshi.io/developers/cli?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=ship-without-rejection&amp;amp;utm_content=article-1" rel="noopener noreferrer"&gt;pre-publish scan you can run in CI&lt;/a&gt;: &lt;code&gt;npx @extenshi/cli scan ./dist/extension.zip&lt;/code&gt;. Fair warning on both tools: they're an automated signal, not a professional audit - for anything high-stakes, have a human lawyer read the final text.&lt;/p&gt;

&lt;p&gt;If this saved you a rejection round-trip, follow to catch new ways to boost your workflow.&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
