Why two codes are worse than one
A conflicting GTIN is not a missing one — the store has too many
answers, not too few. The native GTIN, UPC, EAN, or ISBN
field holds one code, a plugin key like _alg_ean or
_wc_gla_gtin holds another, and each reader picks
whichever field it was built to read.
- The feed and the page contradict each other. A feed built from the plugin's field submits one code while the product page's JSON-LD, built from the native field, carries the other. Google reads both. A code that disagrees with the page it came from is exactly the mismatch that gets an offer disapproved or matched to a product you don't sell.
- Every channel gets its own version. Feed plugins and the CSV export read the native field; the EAN plugin renders its own on the product page and hands it to its own integrations. Two comparison sites can end up filing the same product under two different identities.
- At least one code is wrong — silently. Both fields render, both look filled, nothing errors. One of the two codes points at the wrong product, or at nothing, and no report in WooCommerce will ever put the two values next to each other.
- Every future fix inherits the doubt. A migration to the native field, an export for an agency, a marketplace onboarding — each one starts with the same unanswered question of which code to carry forward, multiplied by every conflicted product.
How to find conflicting GTINs manually
Both values live in postmeta, so the check is a self-join: one alias
for the native _global_unique_id, one for the plugin's
key. This WP-CLI query lists products where both fields hold a value
and the values differ:
wp db query "SELECT p.ID, p.post_title,
g.meta_value AS native_gtin, e.meta_value AS plugin_gtin
FROM wp_posts p
JOIN wp_postmeta g
ON g.post_id = p.ID AND g.meta_key = '_global_unique_id'
LEFT JOIN wp_postmeta e
ON e.post_id = p.ID AND e.meta_key = '_alg_ean'
WHERE p.post_type IN ('product', 'product_variation')
AND p.post_status = 'publish'
AND g.meta_value != ''
AND e.meta_value != ''
AND g.meta_value != e.meta_value
ORDER BY p.ID;"
Adjust the table prefix if yours isn't wp_, and swap
_alg_ean for the key your stack writes —
_wc_gla_gtin, fb_gtin,
_wpm_gtin_code and the rest each need their own run.
The query finds the disagreements; it cannot settle them. SQL won't compute a GS1 checksum, so every row still needs both codes validated by hand, and the honest cases — where both codes are well-formed — need someone to check the physical product or the supplier sheet before either field is touched. And the comparison only covers the one key you joined on.
How CatalogLift finds it
Every scan reads the native field and the plugin fields of each product in the synced catalog — the same source-aware reading as the hidden-code check, so a configurable or serialized plugin key is read the way its plugin wrote it. A product where both a native and a plugin value exist and differ becomes a finding at medium severity, and the evidence shows both codes and where each one lives: the value, the source, the exact meta key. The disagreement stops being invisible; it is two named values side by side.
Then each code runs through deterministic validation — the GS1 mod-10 checksum, mod-11 for ISBN-10 — and the evidence marks which of the two values passed. When the plugin's code is the only one that passes, the proposal is pre-filled with it: writing it into the native field is the change that ends the disagreement. When the native code is the one that passes, nothing is pre-filled — the native field already carries the right value, and the plugin's field is corrected in the store, which CatalogLift never writes. When both codes pass, the proposal field is left empty on purpose: two valid codes are two claims about the world, and no checksum — and no AI, which never produces or picks a code here — can tell which one is on the box. You decide, inside CatalogLift, with both values in front of you; CatalogLift writes only what was decided to WooCommerce, and the next scan verifies the fields finally agree. The first scan costs nothing and needs no card.