WooCommerce products that share the same image

One photo standing behind several different products makes a category page read like a stack of copies. CatalogLift finds every image that more than one published product shows — as its main image, in its gallery, or both — and names the products that collide, so the person with the camera knows exactly where to point it.

Images & media Medium severity Detection + evidence

Why a shared image holds products back

The featured image is the product wherever the store shows a grid: the shop page, category archives, related products, search results, the cart, and the product feed your ads read from. The gallery is where a shopper goes to be sure. Shoppers scan the pictures, not the titles. When two products carry the same picture, the grid stops telling them anything.

  • Listings look like duplicates. The same photo four times in a row reads as a mistake or a lazy import, and shoppers skip past all four rather than open each one to find the difference.
  • Feeds and marketplaces notice. Google Merchant Center and marketplace channels compare image links across items; several products pointing at one file get treated as near-identical listings, and the whole feed's quality suffers.
  • A borrowed gallery photo misleads just as well. The shopper who opens the gallery to check the fabric is looking at another product's fabric, and the return says the picture was wrong.
  • Returns go up. A shopper who bought the blue variant off a photo of the grey one sends it back — and the review says the picture was wrong, not that they clicked the wrong item.
  • Placeholders quietly become permanent. A supplier import that sets one stock photo on a whole line looks finished in wp-admin, so nobody goes back to shoot the real products.

How to find shared product images manually

WooCommerce keeps the featured image as an attachment ID under the _thumbnail_id meta key and the gallery as a comma-separated list under _product_image_gallery. One query has to read both and then count the distinct products behind each attachment:

wp db query "SELECT attachment_id, COUNT(DISTINCT product_id) AS products,
       GROUP_CONCAT(DISTINCT product_id ORDER BY product_id) AS product_ids
FROM (
  SELECT m.post_id AS product_id, m.meta_value AS attachment_id
  FROM wp_postmeta m
  JOIN wp_posts p ON p.ID = m.post_id
  WHERE m.meta_key = '_thumbnail_id' AND m.meta_value <> ''
    AND p.post_type = 'product' AND p.post_status = 'publish'
  UNION ALL
  SELECT m.post_id, TRIM(j.value)
  FROM wp_postmeta m
  JOIN wp_posts p ON p.ID = m.post_id
  JOIN JSON_TABLE(
    CONCAT('[\"', REPLACE(m.meta_value, ',', '\",\"'), '\"]'),
    '$[*]' COLUMNS (value VARCHAR(20) PATH '$')
  ) j
  WHERE m.meta_key = '_product_image_gallery' AND m.meta_value <> ''
    AND p.post_type = 'product' AND p.post_status = 'publish'
) usages
GROUP BY attachment_id
HAVING products > 1
ORDER BY products DESC;"

Adjust the table prefix if yours isn't wp_. The gallery half needs MySQL 8 for JSON_TABLE; on MariaDB the list has to be split in application code instead.

This works, with gaps. It hands you attachment numbers, not products you can open, so every row means another lookup. It does not say which product shows the photo where, so it cannot tell you whether you are looking at two listings wearing one face or a gallery that borrowed a picture. It ignores whether the attachment still exists, so a deleted file that a dozen products still point at shows up as a shared image rather than a missing one. And it answers once: the next supplier import can set the same stock photo on thirty new products, and nobody runs the query again.

How CatalogLift finds it

Every scan reads the images of each published product in the synced catalog — the main image and the gallery together — and groups them by the attachment they point at. An attachment more than one distinct published product shows produces a finding on each of those products. A product showing the shared photo as its main image is rated medium; one that only carries it in a gallery is rated low, because a borrowed gallery picture misleads later in the journey than the face of a listing. A product that shows the same photo in both places gets one finding naming both, not two findings — the same image twice inside one product is the repeated gallery image check's business, and it stays there.

Only published products count, on both sides of the collision, so a draft copy that kept the original's images never earns the original a finding. An image the store no longer has as a live attachment is left to the missing-image checks rather than reported here.

Each finding carries evidence: the image itself, where this product shows it, how many products stand behind it, and a sample of the others by name and by the place each one shows it. Because the count is taken across the whole store even on a targeted re-scan, a shared image is never reported as resolved just because its twin fell outside the products being rechecked. And when one product gets a photo of its own, the findings on the products that never moved close as a group collapse — nobody is handed a receipt for work they did not do.

This is a detection-and-evidence check. A photo of the product itself is the one thing CatalogLift cannot write for you, so the change is made in WooCommerce: open the product, go to the box the case names — Product image or Product gallery — put the right photo there, save. This is a hand-off: CatalogLift cannot make this change for you and neither can an agent, so nothing in your store moves until somebody uploads that photo. The next scan confirms the finding is gone. Because CatalogLift keeps watching, an import that reuses one photo across a new line becomes a fresh finding instead of a silent regression.

Fair questions, straight answers.

Why is one photo on several products a problem?

The image is what shoppers actually scan — on category pages, in search results, in feeds and in the cart. When two different products show the same photo, shoppers cannot tell them apart at a glance, feeds treat them as near-duplicates, and returns rise because the picture did not match what arrived.

Does this cover gallery images or only the main one?

Both, and every combination of them. Two products with the same featured image, one product's main image sitting in another product's gallery, and one photo appearing in two galleries are all the same fact: that image does not belong to one product. Each case says where this product shows it, and a product using the shared photo as its main image is rated higher than one carrying it further down a gallery.

Does CatalogLift count draft products?

No. Only published products count, on both sides of the collision. A draft made with WooCommerce's own Copy to a new draft keeps the original's images, and counting it would give an untouched published product a finding for a copy no shopper can reach.

What about the same image twice inside one product?

That is a different check. A gallery repeating a photo the product already shows is a mistake in one product's own assignment, and it has a fix CatalogLift can apply for you — see repeated gallery images. This check only speaks when the image reaches past the product it belongs to.

Can CatalogLift replace the shared image for me?

No. A photo of the product itself has to come from your camera or your supplier, and the connector has no way to write a product's images. CatalogLift finds the collision, says where each product shows the photo, names the other products standing behind it, and links you to the edit screen; once you put a photo of its own in WooCommerce, the next scan confirms the finding is gone.

What if the shared photo is deliberate, like one placeholder for a whole line?

The finding still stands, because it describes what shoppers see: several listings showing the same picture. You decide which of the products need their own photo and which can wait — and CatalogLift keeps the group in view until they do. If your catalog shares images on purpose, the check can be switched off for the store.

See it on your own catalog.

Create a free account, connect your WooCommerce store and this check runs on your real products, along with the rest.

No card required. The free plan never writes to WooCommerce.