The identifier on a product is what lets an AI surface decide whether the catalog is talking about a real, specific item or something generic. A title and description say “a wool sweater”; a GTIN says “this specific wool sweater, manufactured by this brand, with this UPC.” The difference is whether the product can be matched, deduplicated, and trusted across thousands of catalogs referencing the same thing — or whether it sits in an unidentified pile of look-alikes.
Most ecommerce catalogs do not treat identifiers as load-bearing. The legacy assumption is that they matter mainly for marketplace listings (Amazon, eBay) and feed delivery (Google Merchant Center). The shift over the last few years is that AI surfaces have started weighing identifiers heavily for the discovery and deduplication work too — meaning a private-label catalog without GTINs is now competing for visibility against branded catalogs that have them, and losing.
This guide names the three main identifier types (GTIN, MPN, brand), explains when each applies, walks through how to source them, and shows the Shopify-specific patterns for putting them in the structured-data layer.
The decision flow for which identifier(s) to emit:
What each identifier is
Four identifier categories show up in Schema.org and in AI surface ingestion:
| Identifier | What it identifies | Authority | Schema.org property |
|---|---|---|---|
| GTIN | A specific manufactured item (the SKU as the manufacturer ships it) | GS1 | gtin13, gtin12, gtin8, gtin14 |
| MPN | The manufacturer’s internal part number | The manufacturer | mpn |
| Brand | The brand the product is sold under | The brand owner | brand |
| SKU | The merchant’s internal identifier | The merchant | sku |
The first three are external, authoritative identifiers. The fourth (SKU) is internal to a merchant and is not interchangeable across catalogs.
GTIN
GTIN is the global identifier issued by GS1, the international body that manages the UPC, EAN, ISBN, and JAN systems. The 12-digit UPC found on most North American retail packaging is a GTIN-12; the 13-digit EAN used in Europe is a GTIN-13; ISBN, the identifier for books, is a GTIN-13 in disguise.
In Schema.org, GTINs go in one of:
gtin13— 13 digits, the canonical international formatgtin12— 12 digits, the North American UPCgtin8— 8 digits, used for small items where there isn’t room for a longer codegtin14— 14 digits, used for shipping containers and multi-pack groupingsgtin— a polymorphic alternative that accepts any of the above
Schema.org’s recommendation since
2023 is to use the specific format (gtin13, etc.) rather than
the polymorphic gtin. Use the specific form whenever you know
which format applies.
MPN
The Manufacturer Part Number is the manufacturer’s identifier for the part — the code the manufacturer assigns to a specific model in its catalog and uses across documentation, packaging, and downstream feeds. Unlike GTIN, MPN is not issued by a global authority; the manufacturer decides the format. A buyer searching for “Sony WH-1000XM5” is searching the MPN that manufacturer assigned. MPN is distinct from a retailer’s SKU, which is internal to a single merchant.
MPN matters because:
- For products without a registered GTIN, MPN + brand can serve as the identifying pair (the GTIN-or-MPN-plus-brand-allowed-by-Google rule).
- B2B catalogs and configurable products often have MPN even when GTIN isn’t registered.
- AI surfaces use MPN as a fallback identifier when GTIN is absent — especially for electronics, automotive parts, and other domains where MPN is the standard.
Brand
brand is a sub-object on Product (and Offer) that names
the brand. Best expressed as a Brand or Organization
object — see Organization
schema
for the cross-reference pattern.
For private-label catalogs, the merchant is the brand. The
brand.name should be the consumer-facing brand under which the
product is sold (e.g., “Acme Outfitters”), not the merchant’s
legal entity name (e.g., “Acme Outfitters, LLC”) if those differ.
SKU
sku is the merchant’s internal identifier. It is not
interchangeable across catalogs (each merchant has their own SKU
system) but is useful as a stable per-merchant identifier and as
a cross-reference into the merchant’s ERP or order-management
system.
sku does not serve the deduplication role that GTIN does. A
product with only an sku is identifiable inside the merchant’s
data but not across the open web.
The GTIN-or-(MPN+brand) rule
The practical question every catalog faces: “do I need a GTIN specifically, or is MPN + brand enough?”
For pure-merchant work (just emitting structured data) the answer is: GTIN is preferred everywhere; MPN + brand is an acceptable fallback in domains where MPN is the standard (electronics, parts, B2B). For most product categories, GTIN wins.
For Google Merchant Center, the rule is more explicit (per Google’s structured-data product docs):
- New products from a brand: GTIN required if the brand publishes one.
- Private-label products: GTIN preferred, MPN + brand accepted.
- Custom or unique products: identifierExists: false declared on the feed.
The trend across surfaces since 2023 has been to treat GTIN more strictly. A catalog operating without GTINs is meaningfully disadvantaged versus competitors that have them.
Why private-label catalogs need GTINs now
Five years ago, the standard advice to a private-label brand (“we manufacture our own products, why do we need a GTIN?”) was that GTINs were optional unless selling through marketplaces. That advice has changed.
The reasons:
1. AI surfaces deduplicate aggressively. A product without an external identifier is treated as a candidate match for any similar-looking product the surface has seen. The surface picks the version it can identify confidently; the unidentified version gets demoted to “see also.”
2. Google Merchant Center signaling. GMC’s identifier handling has evolved — in some categories products without GTINs now receive warnings rather than disapprovals (see Google’s identifier-existence documentation), but missing identifiers still suppress eligibility for some shopping placements and reduce confidence in the product graph that feeds AI Overviews and Gemini. The trend is more nuance, not less consequence.
3. Counterfeit pressure. AI surfaces handling potentially- counterfeit categories (electronics, beauty, supplements) weigh identifier presence as a trust signal. A private-label product without a registered GTIN looks structurally similar to a counterfeit on the data side.
4. Cross-platform consistency. If the brand wants to expand to a marketplace, a second platform, or a wholesale arrangement later, the GTIN is what unifies the product identity across those channels. Starting with a GTIN avoids retroactive re-identification.
5. The cost is low. GS1 issues GTIN prefixes for a one-time fee plus a small annual renewal. The work to register a brand’s GTIN range is hours, not weeks. The marginal cost per product is nominal.
For most private-label catalogs that have not yet registered GTINs, the operational recommendation is: register a GS1 prefix, assign GTINs to existing products, and update the catalog’s structured data and GMC feed with the new identifiers. The cleanup is real work but the long-term cost of not doing it is larger.
How to source GTINs
Three paths depending on the brand’s setup:
Brand-owned products (registered GS1 GTINs). The brand registered with GS1 and was assigned a GS1 Company Prefix, which lets them issue GTIN-12 or GTIN-13 codes for their own products. This is the canonical path for private-label catalogs.
Reseller products (using the manufacturer’s GTINs). A reseller selling another company’s branded products uses the GTINs the manufacturer assigned. The merchant’s responsibility is to source the right code per product. Often the GTIN is printed on the product packaging or shipping carton; a more scalable source is the supplier’s data feed or a wholesale ERP integration.
Mixed catalogs. A catalog with both private-label and
reseller products needs to track which is which and source GTINs
through both paths. Common pattern: a Shopify metafield
custom.gtin_source per product noting “self-issued”,
“manufacturer”, or “unregistered” so the data lineage is
auditable.
A useful tactic for catalogs with unidentified products: do a one-time bulk lookup against GS1’s GEPIR service or a third-party UPC database. Most products in established categories have GTINs registered somewhere; the merchant’s job is to find and attach them.
Where to put identifiers in Shopify
Shopify stores GTIN by default in the barcode field on each
variant. The field is per-variant (which matches Schema.org’s
structure — each variant has its own GTIN).
Setting GTINs:
- Admin UI: Products → product page → variant editor → “Barcode (ISBN, UPC, GTIN, etc.)” field
- Bulk via CSV: the
Variant Barcodecolumn in Shopify’s product CSV export/import - Programmatically: Shopify Admin GraphQL API,
productVariant.barcodefield
For MPN, Shopify has no native field. Most catalogs use a
metafield: namespace custom, key mpn, type Single line text. The metafield can be exposed in the storefront and
referenced from Liquid.
Brand is typically stored in the product’s vendor field by
default. This is acceptable when the brand and vendor are the
same (the common case); for catalogs where they differ, use a
metafield (custom.brand) and reference it from Liquid.
The Liquid that emits all three
For a single product, in the JSON-LD block:
"sku": {{ product.selected_or_first_available_variant.sku | json }},
{%- if product.selected_or_first_available_variant.barcode -%}
"gtin13": {{ product.selected_or_first_available_variant.barcode | json }},
{%- endif -%}
{%- if product.metafields.custom.mpn -%}
"mpn": {{ product.metafields.custom.mpn.value | json }},
{%- endif -%}
"brand": {
"@type": "Brand",
"name": {{ product.vendor | default: shop.name | json }}
}
For a variant product, the same pattern moves inside each
variant in hasVariant:
{%- for variant in product.variants -%}
{
"@type": "Product",
"sku": {{ variant.sku | json }},
{%- if variant.barcode -%}
"gtin13": {{ variant.barcode | json }},
{%- endif -%}
{%- if variant.metafields.custom.mpn -%}
"mpn": {{ variant.metafields.custom.mpn.value | json }},
{%- endif -%}
// ... rest of the variant block
}
{%- endfor -%}
A few practical notes:
- The
barcodevalue in Shopify can be empty for products without registered GTINs. The conditional{% if %}guards prevent emitting"gtin13": "", which validators flag. - Shopify’s
barcodefield doesn’t validate the format. A manually-entered value can be 12 digits, 13 digits, or garbage. Trust the data and usegtin13only when the value passes a 13-digit format check; otherwise use the polymorphicgtinand let the parser figure out the format. - For metafields to be available in Liquid, they need to be defined in the Shopify admin first (Settings → Custom data → Products).
Identifier format checks
A simple Liquid helper to emit the right gtin* variant based
on length:
{%- assign bc = variant.barcode | strip -%}
{%- if bc.size == 13 -%}
"gtin13": {{ bc | json }},
{%- elsif bc.size == 12 -%}
"gtin12": {{ bc | json }},
{%- elsif bc.size == 8 -%}
"gtin8": {{ bc | json }},
{%- elsif bc.size == 14 -%}
"gtin14": {{ bc | json }},
{%- elsif bc.size > 0 -%}
"gtin": {{ bc | json }},
{%- endif -%}
This handles the most common case (a 12- or 13-digit GTIN) and
falls back to the polymorphic gtin for unusual lengths.
The seven failure modes
Identifier issues that show up most often:
1. Empty barcode field across the catalog
The most common pattern. The catalog never registered GTINs and
all variants have empty barcode. The JSON-LD output either
omits the GTIN property entirely (good) or emits
"gtin13": "" (bad — validators flag, AI surfaces have to
parse and discard).
Fix: source GTINs (per “How to source GTINs” above) and use conditional emission. Empty strings should never reach the structured data.
2. GTIN format mismatch
The Shopify barcode field has a value, but it is emitted under
the wrong Schema.org property — a 14-digit value pushed into
gtin13 rather than gtin14, or a UPC-A pushed into gtin13
without left-padding. The result is markup that doesn’t cleanly
match the GS1 standard’s defined formats. Validators flag the
mismatch.
Fix: use the Liquid format-detection pattern above to pick the right property for the length. GTIN-14 is a distinct identifier used for cartons and multi-pack groupings, not a substitute for GTIN-13.
3. Same GTIN across multiple products
Common in two cases:
- The merchant entered a placeholder GTIN (“1234567890123”) on multiple products
- A bulk import mapped a single column incorrectly
Result: AI surfaces detecting duplicate GTINs treat the catalog as low-quality. GMC disapproves all but the first.
Fix: audit for duplicates (Shopify reports list variants by barcode; a CSV export sorted by barcode surfaces dups quickly). Replace placeholder values with real GTINs or empty strings.
4. Brand left as vendor when they differ
A reseller storefront where the vendor field has the
manufacturer name correctly, but a private-label storefront
where the vendor field has the merchant’s legal entity name
instead of the consumer-facing brand name.
Fix: use a custom.brand metafield for the consumer-facing
name. The vendor field can stay as the legal entity for
internal use.
5. MPN emitted as a string of the SKU
Common when the catalog has no real MPN data and the Liquid defaults to using the SKU. The MPN claim is false; AI surfaces that cross-reference MPN against manufacturer catalogs see a mismatch.
Fix: omit mpn entirely when no genuine MPN exists. Don’t fall
back to SKU.
6. brand as a bare string
The Schema.org spec accepts brand as either a string or an
Organization/Brand object. Validators don’t reject the
string form, but AI surfaces have less to work with — no logo
URL, no sameAs cross-references, no @id for stable
identity.
Fix: emit brand as a Brand object with at minimum name,
preferably referencing the site-wide Organization block by
@id.
7. Inconsistent identifiers between page and feed
The Shopify product page emits gtin13: "0840062303849" in
the structured data; the Google Merchant Center feed emits
gtin: "840062303849" (without leading zero). Both are the same
underlying GTIN but the formats differ. AI surfaces seeing both
have to reconcile; this is sometimes done correctly, often not.
Fix: normalize the format at the source. Either pad to 13 digits consistently or leave at 12; emit the same form in the page and the feed.
What about products without GTINs?
For genuinely unique products (custom, handmade, art) the right
answer is identifierExists: false in the feed and omission of
GTIN/MPN in the structured data. The Schema.org pattern:
"identifier_exists": false
is a Google Merchant Center field more than a Schema.org property — Schema.org expresses this implicitly by omitting the identifier properties.
In structured data, simply omit gtin* and mpn. Include sku
and brand. AI surfaces treat the product as identifiable by
brand + name but not by external identifier; the citability is
lower than for an identified product but acceptable for unique
inventory.
Cross-platform identifier consistency
For brands selling on multiple platforms (own site + Amazon + a B2B portal), the identifier should be the same across all platforms. The brand-side discipline is:
- Assign a single GTIN per SKU at the catalog master record.
- Push that GTIN consistently to every channel.
- Treat platform-specific differences (Amazon’s ASIN, eBay’s item number) as channel identifiers separate from the GTIN — they coexist with the GTIN, not replace it.
This unifies AI surface ranking: a product cited on Perplexity by GTIN and a product cited on ChatGPT by GTIN are the same product in the surface’s representation, even if the cited URLs differ.
Related reading
- Product schema for Shopify — the Schema.org reference where identifiers appear in context.
- Organization schema: brand identity in structured
data —
the cross-reference pattern for
brand. - Google Merchant Center setup — the feed-side identifier rules.
- Validating structured data — verifying identifiers parse correctly.
- GS1 GTIN reference — the canonical identifier authority.