Short answer. Since WooCommerce 9.2 every product and every variation has a field labelled GTIN, UPC, EAN or ISBN in the Inventory tab. Put the number under the product’s barcode there (8, 12, 13 or 14 digits), leave it empty for products that genuinely have none, and a feed plugin that reads the field sends g:gtin when it is filled and g:identifier_exists = false when it is not. That pair is what clears Google’s missing- identifier warnings without ever inventing a barcode.
The field, and what it is not
WooCommerce’s 9.2 release notes describe it: a new field called global_unique_id, labelled “GTIN, UPC, EAN or ISBN”, added to the product editor for main products and variations, stored in its own column and enforced unique across the catalogue, the way a SKU is. Before 9.2 there was no such field in core; barcodes lived in plugin fields and custom meta, each feed plugin reading its own, and Google saw whatever happened to be mapped.
It is not the SKU. The SKU is your code for the product in your shop; the GTIN is the manufacturer’s code for the product everywhere, and Google validates it. WooCommerce keeps the two apart for that reason, and so should the feed: a SKU written into g:gtin is a disapproval, and a SKU written into g:mpn is a claim that your internal code is the manufacturer’s part number, which it is not.
What to enter
The number printed under the barcode, digits only. Google’s gtin specification accepts 8 digits (EAN-8), 12 (UPC-A), 13 (EAN-13, and ISBN-13) or 14 (ITF-14), and checks the last digit against the others, so a typo is caught. GS1 is the body that issues them; a real GTIN has a prefix registered there. Three habits keep the field honest:
Keep leading zeros. A UPC that starts with 0 is twelve digits with the zero; a spreadsheet that treats the column as a number drops it and produces an eleven-digit value Google rejects. Format the column as text before pasting.
One barcode per variation. The red Medium and the red Large have different GTINs. Fill the field on each variation; a value on the parent is only a fallback.
Nothing rather than something. No placeholders (0000000000000, N/A), no supplier codes, no barcode of a different pack size. An empty field is a valid state Google understands; a wrong value is not.
Products without a barcode
Handmade goods, made-to-order items, vintage, own-label products you never registered with GS1: these have no GTIN, and Google’s identifier_exists attribute is how you say so. Set to false, it tells Google not to expect a GTIN, MPN or brand for that product, and the missing-identifier warnings stop. Set to false on a product Google can see is a branded, barcoded item, it is reported as “Incorrect value [identifier_exists]”, so the declaration has to be true per product. For resold goods with no barcode to hand, the alternative Google’s identifier overview allows is brand plus the manufacturer’s part number together.
How the field becomes a feed
Our free plugin reads the 9.2 field for each variation, falling back to the parent product’s value, and writes g:gtin when there is one. When the field is empty it writes g:identifier_exists as false instead, and it never sends the SKU as an MPN. So the whole job on the WooCommerce side is filling the field where a barcode exists and leaving it empty where none does; the feed says the right thing in both cases.
On Google’s side, a filled GTIN lets Merchant Center match your product to its catalogue entry, which is where richer listings and comparison placements come from; an empty one with the declaration runs without those; a missing one with no declaration runs with “Limited performance due to missing identifiers”; and a malformed one is disapproved.
Filling a whole catalogue
For a few dozen products, the product editor is fine. For hundreds, export the products to CSV, check whether your WooCommerce version’s exporter includes the GTIN column (export one product and look), fill the column from your supplier’s list with the column formatted as text, and import with “update existing products”. If the exporter does not carry the column yet, a bulk-edit plugin that exposes the field does the same job. Either way, run the free feed check on the feed afterwards: it validates every GTIN by length and check digit, treats invalid ones as missing, and counts the products still without one.
Questions merchants ask
I am on a WooCommerce version older than 9.2. Where does the GTIN go?
There is no core field before 9.2, so barcodes lived in plugin fields or custom meta. Update WooCommerce: the field arrives with the update and the feed plugins that read it start working. Moving existing values across is a one-off export and import.
Can I put the SKU in the GTIN field to get rid of the warning?
No. A SKU is your own code; a GTIN is the manufacturer’s, with a fixed length and a check digit. A SKU in the field is reported by Google as “Invalid value [gtin]” and disapproves the product, which is worse than the limited-performance warning for a missing one.
My products are handmade. What goes in the field?
Nothing. Leave it empty and let the feed declare identifier_exists as false, which tells Google the product has no manufacturer identifier and stops the warnings. Our plugin does that for every product whose field is empty.
Does the field need to be filled on the parent or on the variations?
On the variations, when the product has them: each size and colour has its own barcode. The plugin reads the variation’s field first and falls back to the parent’s, so a parent-level value is used for variations that have none of their own.
Sources
WooCommerce’s 9.2 pre-release notes (the global_unique_id field) and Variable Products documentation (the field per variation); Google Merchant Center Help on gtin, identifier_exists and unique product identifiers; GS1 on the Global Trade Item Number; and the readme of FeedRobin Product Feed for WooCommerce.