Shopify products missing from Google Shopping: the half you can actually measure
Key takeaways
- A product goes missing in one of three places, and only the middle one is visible from outside your admin. Working out which is yours takes five minutes and saves you from fixing the wrong thing. The most common one is not in this article, so there is a path for it below.
- The image floor moved. Google's product data specification now reads: "We recently announced new image size requirements of at least 500 x 500 pixels for all product images. Enforcement of the new requirements will begin January 31, 2027." (source, read 1 September 2026)
- Against that floor, 20 of the 42 stores we read have at least one product whose main image is too small, against 10 of 42 at a 250-pixel baseline. The product count goes from 684 to 5,118, but 3,226 of those 5,118 sit in one store and 1,304 in the next, and the median store has none at all — this is a condition some catalogues have completely rather than one most catalogues have a little of.
- The price mismatch every guide leads with turned up once in 73 product pages — 41 of 41 in-stock pages agreed with their own catalogue, and 31 of 32 sold-out pages did, with one page quoting a price that appears nowhere in that store's catalogue. That comparison also had less room to fail than it looks, and we say how much below.
- Identifiers are the quiet gap. A GTIN appeared in the page markup on 5 of 41 pages. Brand is not missing from these catalogues — not one of 52,489 products had an empty vendor field — but it reached the page's structured data on only 32 of 41.
- What no public measurement can reach: your feed, your Merchant Center account, and whether the channel ever received the product.
Published 1 September 2026 by Adot Technologies Inc, the team behind Arvio. Storefront figures were read on 1 September 2026 from endpoints any browser can fetch; every requirement quoted comes from Google's product data specification, read the same day. Method, sample and exclusions at the end.
The quick version
Find out which of the three failures you have before you fix anything, because two of them are not about your product data at all. Then start with the images — the floor moved, the deadline is real, and it is the one requirement in this article that a lot of catalogues fail today.
Three different places a product goes missing
"Missing from Google Shopping" describes three failures with nothing in common except the symptom.
It never reached the channel. The product exists in Shopify and was never sent: not published to the Google sales channel, or excluded by the market and country settings the channel runs on. Nothing about the product is wrong; nobody asked Google to look at it. This is the most common version, and it is the one this article's measurements cannot see — so here is where to look instead. Open the product in your admin and find its publishing card, the one that lists the sales channels the product is on. If the Google channel is not there, no amount of editing the product data will help, and the fix is one checkbox rather than a project. Do the same check on the market or country you are expecting to appear in.
It reached Merchant Center and was rejected. An item-level disapproval, and Merchant Center names the reason: a missing required attribute, an image it could not use, a value in your feed that does not match your landing page. This is the layer people mean by "feed problems", and the rest of this article is about the part of it you can inspect without an account.
It was accepted and is not appearing. An eligibility rule, a policy, a country, or nothing you sell matched the query. There is no fix list because there is no fault.
Telling them apart. Open your Merchant Center products list and search for the product. Not there at all: the first case, and the publishing card above is where you go. Listed as disapproved or with an issue: the second, and Google has already told you which requirement. Listed as active and still not visible: the third, and the useful move is your country and shipping setup rather than editing products. Merchant Center is a separate Google product from your Shopify admin; if you are not sure you have an account, that answer is itself worth having before you read further.
What the specification actually asks for
The product data specification sorts every attribute into tiers — required, "it depends", optional — and is blunt about the first: leave a required attribute out and the product cannot serve. The requirements a storefront exposes from outside are a short list: a title of at most 150 characters, a description, an image, a price, an availability value, and a brand — required, in Google's phrasing, "For all new products, except movies, books, and musical recording brands". GTIN sits in the third category, "It Depends (strongly recommended if available)", which matters later.
And the sentence this article ends up being about:
"We recently announced new image size requirements of at least 500 x 500 pixels for all product images. Enforcement of the new requirements will begin January 31, 2027."
That short list is what a storefront exposes, so we counted it.
The two causes everyone names, measured
Search this problem and you are told, repeatedly, to check two things: a price that disagrees between your feed and your landing page, and a brand missing from your product schema. Neither claim tends to arrive with a number.
Google compares the value in your feed against the value it reads on your landing page. Nobody outside a merchant's account has their feed, so we measured the other half of the pair: what each landing page declares, against what that same store's own catalogue says its variants cost.
On 41 of the 42 stores the product page carried product structured data, and on all 41 the price in the markup matched a price on a live variant. We ran the same comparison on a sold-out product from each store that had one: 31 of 32 matched, and the one exception quoted a price that appears nowhere in that store's catalogue. So it happens — once in 73 pages — and if you want the shape of the failure, that is it: a number on the page that the catalogue has never heard of.
How much room that comparison had to fail is the part worth knowing. The page markup and the catalogue endpoint are two renderings of the same product record, so agreement is closer to the default state than to a finding. And on 37 of those 41 in-stock products there was only one distinct variant price, meaning there was one number to agree with. Four products had more than one price, and on three of those the markup quoted a subset — a single price where the product has several, which is exactly the shape that produces a mismatch when a feed sends a different variant's price. Every offer node we read was a plain Offer; there were no AggregateOffer nodes and no highPrice values anywhere in the sample.
The conclusion that survives all of that is narrower than "price mismatches do not happen", and more useful: the landing page is not where the divergence is coming from in this sample. If Merchant Center is telling you your price does not match, the value that moved is on the feed side, and the product page is the wrong place to spend the afternoon.
Brand turns out to be a different result than "missing". Every one of the 52,489 products we read had a vendor filled in — not one empty, across 42 unrelated stores, which is a distribution that usually means the field cannot be left empty rather than that every merchant filled it in. But brand reached the page's structured data on only 32 of the 41 pages with a product node. So the information is in the catalogue and on nine pages the theme did not put it where a machine reads it. If you want to know whether that is you, run the second snippet below on one of your own product pages: it is a theme question, so one page answers it for the store. A separate thing worth knowing: on 8,260 products across 31 of the 42 stores, the vendor looks like the store's own name — meaning that after lowercasing and removing spaces and hyphens, the vendor either equals the first part of the store's domain or one contains the other. That is a deliberately loose rule and it catches own-brand stores, which are a normal thing to be. Whether Google treats a house brand as a brand is not something we can measure from outside, and we are not going to assert it.
The image floor moved
| Main product image | Products | Stores with at least one |
|---|---|---|
| Below 250 pixels on the short side — our baseline, not a Google rule | 684 | 10 of 42 |
| Below Google's 500 x 500 requirement | 5,118 | 20 of 42 |
Read the first row carefully, because we are not going to dress it up: 250 is a comparison baseline we chose, not a threshold we can quote. Google's older minimums varied by product category, we did not classify these catalogues, and the specification we read gives one number, 500. The row exists so that both lines are measured with the same caliper against the same sample; it is not a claim about who was failing which old rule.
Both rows count the main image only — the first image on the product, which is the one a feed uses for image_link. Measured the loose way, counting a product if any of its images is under 500 pixels, it is 6,080 products across 25 stores. We are quoting the strict number.
The honest headline here is the store column, not the product column. The product count is dominated by two catalogues: the worst store holds 3,226 of the 5,118 and the next holds 1,304, the median store has none at all, and those same two stores are also the two worst at the 250 baseline. So the product ratio between the two rows is mostly a fact about two stores, and we are not going to quote it as a multiplier. The store count is the durable number: at 250, ten of these forty-two stores had a problem; at 500, twenty do.
The pattern behind it is ordinary. Product photos get sized once, for a theme, at whatever the grid needed, and never re-cut. If yours are 400 pixels square, every one of them is now below the floor.
What that costs you is worth saying plainly, because it is the part the fix lists skip. Re-cropping in the theme does not change the file. If you still have the original photographs you can re-export them larger and the job is an afternoon of uploading. If 400 pixels is all you have — supplier images, an old export, a store built before anyone asked — then this is not a data fix, it is a photography budget, and it has a date on it. Sixteen months is enough time to do it a hundred products at a time, and it is not enough time to discover in January 2027.
Two edges on the measurement. The pixel dimensions come from the store's own catalogue endpoint, so we are reading what Shopify reports for each uploaded file rather than re-downloading and measuring every image. And a product below the floor today is not disapproved today; the specification gives a date.
The identifier gap
Of the 41 pages carrying product structured data, a GTIN appeared on 5. A SKU appeared on 21. An MPN appeared on 1.
Structured data on the page is not your feed, and a barcode stored in your Shopify admin does not have to appear in the page markup to reach Merchant Center — the two travel by different routes. What the number does say is that you cannot audit your own identifier coverage by looking at your storefront: the products endpoint does not carry barcodes at all, and the page markup carried one about an eighth of the time. We measured the same field from a different angle in what 58 live stores actually serve as schema markup.
Since GTIN is "strongly recommended if available" rather than required, this is not a disapproval waiting to happen. It changes how a product competes, not whether it can appear — and it is one of the few things on this list where the answer really is in your admin rather than on your storefront.
Check your own catalogue
Open your storefront, open the developer console, paste this. It reads the same public endpoint a feed reads.
const flagged = [], seen = new Set();
let page = 1, total = 0, incomplete = '';
while (true) {
if (page > 200) { incomplete = 'stopped at the 200-page safety limit'; break; }
let products;
try {
const r = await fetch(`/products.json?limit=250&page=${page}`);
if (!r.ok) { incomplete = `page ${page} returned HTTP ${r.status}`; break; }
({ products } = await r.json());
} catch (err) {
incomplete = `page ${page} did not return usable JSON (${err})`; break;
}
if (!products || products.length === 0) break; // an empty page is the end; a short page is not
for (const p of products) {
if (seen.has(p.id)) continue;
seen.add(p.id); total++;
const text = (p.body_html || '').replace(/<[^>]*>/g, '')
.replace(/ | | /gi, ' ').trim();
const imgs = p.images || [];
const sized = imgs.filter(i => i.width && i.height);
const why = [];
if ((p.title || '').length > 150) why.push(`title ${p.title.length} chars`);
if (!text) why.push('no description');
if (!imgs.length) why.push('no image');
else if (!sized.length) why.push('image dimensions not reported — check this one by hand');
else if (Math.min(sized[0].width, sized[0].height) < 500)
why.push(`main image ${Math.min(sized[0].width, sized[0].height)}px`);
if (!p.vendor) why.push('no brand');
if (why.length) flagged.push({ handle: p.handle, why: why.join(' · ') });
}
console.log(`page ${page}: ${total} products so far`);
page++;
await new Promise(r => setTimeout(r, 400));
}
console.log(`${total} products read` +
(incomplete ? ` — INCOMPLETE: ${incomplete}. The count below is a floor.` : ''));
console.log(`${flagged.length} products miss one of the requirements this endpoint can show`);
console.table(flagged.slice(0, 50));
console.log(flagged.map(x => x.handle).join('\n')); // the whole list, not the first fifty
Two things it deliberately does not flag. A sold-out product is not a failure: Google requires an availability value, and out_of_stock is one of the valid ones, which our own sold-out pages confirm below. And it does not check price or the 5,000-character description limit, because neither turns up as an empty field — the label above says "one of the requirements this endpoint can show" rather than "a requirement" for that reason. The no brand check never once fired across our 42 stores; it is in there because your store is not our sample.
Then open one of your own product pages and run this, to see what a machine reads on the landing page:
const nodes = [], seen = new Set();
let broken = 0;
const walk = o => { if (Array.isArray(o)) o.forEach(walk);
else if (o && typeof o === 'object') {
if ([].concat(o['@type'] || []).some(t => String(t).toLowerCase() === 'product')) {
const key = JSON.stringify([o.name, o.sku, o.url]);
if (!seen.has(key)) { seen.add(key); nodes.push(o); }
}
Object.values(o).forEach(walk); } };
const blocks = document.querySelectorAll('script[type="application/ld+json"]');
for (const s of blocks) { try { walk(JSON.parse(s.textContent)); } catch { broken++; } }
const brandOf = b => Array.isArray(b) ? b.map(brandOf).join(', ')
: (b && typeof b === 'object' ? b.name : b);
if (broken) console.log(`${broken} of ${blocks.length} JSON-LD blocks would not parse — ` +
`that is a bug on this page, not an absence`);
if (!nodes.length) console.log(blocks.length ? 'JSON-LD present but no Product node'
: 'no JSON-LD on this page');
if (nodes.length > 1) console.log(`${nodes.length} Product nodes — related-product markup ` +
`counts too; the first is usually this product`);
console.log(nodes.map(n => ({
name: n.name,
prices: [].concat(n.offers || []).flatMap(o => [o.price, o.lowPrice, o.highPrice]
.filter(v => v != null)),
availability: [].concat(n.offers || []).map(o => o.availability).filter(Boolean),
brand: brandOf(n.brand) ?? '(none)',
gtin: ['gtin13','gtin12','gtin8','gtin14','gtin'].map(k => n[k]).find(Boolean) ?? '(none)',
sku: n.sku ?? '(none)',
})));
The separate line for blocks that will not parse is there because the usual cause is a quote mark inside a product description, and "your page has no structured data" and "your structured data is broken JSON" are different problems with different fixes. Note that both this and our survey read JSON-LD only; a theme that expresses the same thing as microdata attributes would read here as having none.
Compare what it prints against the price on the page and against Merchant Center. On the evidence above those three usually agree.
Availability, in one direction
None of the 32 sold-out product pages declared itself in stock in its structured data, and none was missing an availability value entirely. That is the direction that gets written about, and it was clean.
The reverse error — an in-stock product whose markup says out of stock, which also keeps it out of results — is one we did not test. We read an in-stock page from every store and compared its prices, not its availability. So this section covers one direction, and we would rather say that than let "availability came out the same way" carry both.
Fixing the ones that are yours, in order
- Confirm the product is in Merchant Center at all. If it is not, everything below is wasted effort; go back to the publishing card.
- Read the reason Google gives you. Item-level disapprovals are named. Guessing from a symptom is how people rewrite titles for a week to fix an image problem.
- Then the images, because that is the one with a deadline, and because for some catalogues it is a budget rather than an edit.
- Then the empty fields. A missing description or a product with no image at all is a product you are asking Google to list with nothing to list.
- Then the things that only affect how you compete — identifiers, better titles, images past the minimum.
Steps 1 and 2 are reading. Steps 3 to 5 are work, and only step 3 has a date on it.
Doing the counting on a schedule
The free Arvio store audit reads a storefront across six stages and prints each finding with the measurement under it — the same public surface the scripts above read, and the same limits: no admin, no Merchant Center, no Google. On our own demo store it returned findings like "7 distinct category spellings across 69 products | 19 products with no category at all", and it also prints what it declined to check and why. It will not tell you whether you are in Google's index; no tool that only reads a storefront can.
For the recurring half — reading the catalogue, ranking what it found, drafting the edits — Arvio does that against the live store as an installed app with permission to edit products, and its own claim is that nothing is applied until you approve it. Be clear about the boundary this article has just spent 3,000 words drawing: software that edits product data cannot make a 400-pixel photograph bigger. It can find every product that has one and hand you the list. The photographs are yours.
The half of this problem we cannot see
- Your feed. We have never seen one. Every mismatch statement here is about the landing page, which is one side of a two-sided comparison.
- Your Merchant Center account. Approvals, disapprovals, account-level issues, country settings, shipping configuration. None of it is public and none of it is inferable from a storefront.
- Whether the product was ever sent. The most common version of "missing from Google Shopping", and invisible from outside by definition. That is why the admin path is at the top of this article rather than in a footnote.
- GTINs and barcodes. Not on the storefront endpoint. We can see whether the page markup carries one; we cannot see what is in your admin.
- Outcomes. We did not measure whether any of these stores appears in Shopping, or whether fixing any of this changes anything. We measured which requirements a public storefront already meets.
For the organic-search version of this question — a different system with different rules — we measured that separately in why your Shopify products aren't showing on Google. For the same catalogue read as a maintenance backlog rather than a feed, there is a companion piece on the queue your admin cannot show you.
Method
Sample. 42 live Shopify storefronts, read on 1 September 2026, drawn at random from a public list of stores whose owners had posted their own URL on the Shopify Community's Store Feedback board. Everything here came from endpoints any browser can fetch. Stores that ask strangers for feedback skew newer and smaller: the median catalogue is 140 products, the largest 21,683.
The funnel, in full. 720 board topics produced 474 candidate hostnames; 230 were still serving a public catalogue and 244 were not. From the 230 we drew 60 at random with random.Random(20260826).sample, then excluded 16 stores with fewer than 10 published products and 2 that returned no readable catalogue on the day, leaving 42 stores and 52,489 products.
Collection. Read-only GET requests at one request per second with a self-identifying user agent: the products endpoint for the whole catalogue, plus two product pages per store — the first product with something buyable, and the first with nothing buyable. Structured data was parsed from the whole document rather than the first part of it, since these pages run to hundreds of kilobytes and the JSON-LD block is often a long way down.
Requirements. Quoted from Google's product data specification, read on 1 September 2026, and stored verbatim rather than paraphrased. Where a requirement has a threshold we can quote — 150 characters, 500 x 500 pixels — the threshold in our code is the one in the quote. The 250-pixel row is ours, and is labelled as ours in the table.
Price comparison. For each product page, the set of prices in the page's product structured data against the set of live variant prices for that product from the same store's catalogue endpoint, compared as decimals rather than floating point. A page counts as matching when every price the markup declares is a price one of its variants carries. How much discriminating power that has is reported in the body rather than left for you to work out.
Three different counts of 41 appear in this article and they are unrelated: 41 of 42 stores whose product page carried structured data; 41 of 41 of those pages whose markup price matched; and 41 as the number of pages in the brand and identifier counts, which is the same set as the second.
Two implementations. The snippet above and the survey code were run against the same 69-product catalogue — our own demo store, which is not one of the 42 — and both flagged the same 23 products. That shows the two agree, not that the definition is right, and one small store is not a test of either against a real catalogue.
Limits, in one place
- One product page per state, per store. A store can have a correct first product and a broken thousandth one. The structured-data findings rest on 41 and 32 pages, not on 52,489 products.
- Availability in one direction only, as set out above.
- Published products only, so every count here is a floor for a store with drafts.
- Image dimensions as reported, not re-measured, and products whose images report no dimensions are flagged for a manual look rather than silently passed.
- JSON-LD only. Structured data expressed as microdata would read as absent to both our survey and the snippet.
- The 250 row is our baseline, not a Google rule, and is labelled that way wherever it appears.
- Two stores hold most of the image volume. Every figure in that section is given as a store count as well as a product count for that reason.
- No causal claim anywhere. We counted requirements met and unmet on public pages.
FAQ
Why are my Shopify products not showing in Google Shopping?
Three separate failures hide behind one symptom: the product never reached the Google channel, it reached Merchant Center and was disapproved, or it was accepted and is not appearing for what you are searching. Merchant Center tells you which one you have, and the fix is completely different in each case. Start by checking whether the product is listed there at all.
Is a price mismatch between my feed and my product page a common cause?
It is the most commonly named cause, and on the landing-page side we found it once in 73 product pages. Two caveats worth carrying: the page and the catalogue are two views of one record, so agreement is close to the default; and most products in our sample had a single variant price, so there was one number to agree with. If Merchant Center reports a mismatch, look at what your channel is sending.
Does my Shopify theme need to add product schema for Google Shopping to work?
Shopping reads your feed, not your page markup, so it is not a prerequisite in that sense. Google does use the landing page to check the feed against, so markup that contradicts your feed can cause the mismatch above. On our sample, 41 of 42 stores were emitting product structured data.
What image size does Google Merchant Center require now?
The specification asks for at least 500 x 500 pixels, with enforcement beginning 31 January 2027. In our sample that takes the stores carrying at least one undersized main image from 10 of 42 to 20 of 42.
My product images look fine on my store. Why would they be too small?
The theme scales them. A 400-pixel file fills a product page perfectly well at the size a browser draws it, and is still a 400-pixel file, which is what a feed sends. The check in this article reads the stored dimensions rather than what the page looks like.
Do I need GTINs on all my products?
Google puts GTIN in its "It depends" tier, strongly recommended where the product has one. Handmade and own-brand products usually have none, and that is a normal state rather than an error. Missing GTINs do not get a product disapproved.
Where does Shopify store the barcode, and can I check it from outside?
On the variant, in your admin. It is not on the public storefront endpoint, so no external tool — ours included — can audit your identifier coverage. That check happens inside the admin or through a product export.
Is this the same problem as my products not showing in normal Google search?
No. Shopping runs on your feed and Merchant Center; organic results run on crawling and indexing. They fail for different reasons and are fixed in different places, and the organic version is written up separately.
