You added custom.color to every product in Shopify. You configured the mapping in the Google channel. You waited the full review window. Open Merchant Center and the color attribute on those products is still empty.
If you ran through the Shopify metafields to GMC attributes mapping guide and the values still aren't showing up, this is the companion post for you. The mapping you set up is sound; something downstream is dropping the value before Google sees it.
This post covers the seven most common reasons a Shopify metafield gets configured correctly but doesn't reach Merchant Center, ranked by how often each one is the real culprit. Each fix is independent — you can work down the list until the symptom clears.
TL;DR
- The most common cause: the metafield was created on products, but the mapping in the Google channel expects it on variants. Variant-level metafields are a separate object in Shopify and require explicit per-variant population.
- Second: the metafield type is wrong. Shopify lets you define a metafield as
single_line_text_field,list.single_line_text_field,metaobject_reference, etc. Most feed tools only read scalar text. List and metaobject types silently fail to serialize. - Third: the metafield namespace is gated behind Shopify's pinned-definitions policy. If the definition wasn't pinned at the time the product was edited, the value didn't save.
- Fourth: the value contains characters Google strips during parsing (HTML entities, emojis, zero-width spaces), leaving an empty string that fails the attribute check.
- Fifth: the Google channel sync is rate-limited and the metafield update is in a queue you can't see.
- Sixth: variant-level metafields aren't being submitted because the feed plugin only fetches product-level data.
- Seventh: the wrong field name.
custom.colorandmm-google-shopping.colorlook the same and aren't.
How the Shopify → GMC pipeline actually works
Before troubleshooting, it helps to understand what's between your metafield and Merchant Center. There are five hops:
- Shopify Admin or API write. You or a script sets a metafield value on a product or variant.
- Shopify metafield storage. The value persists in Shopify's database, scoped to a namespace + key on a specific owner (Product, Variant, ProductVariant, etc.) with a declared type.
- Feed tool fetch. The Google channel app or a third-party feed tool (DataFeedWatch, Channable, SnowPipe, etc.) reads the metafield via Shopify's GraphQL Admin API, typically nightly or on-demand.
- Mapping and transformation. The tool applies its configured mapping (
custom.color→color), runs any normalization rules, and adds the result to the outbound feed or API payload. - Submission to Google. The tool either pushes a feed file to Merchant Center or calls the Merchant API directly.
A failure at any of these five hops produces the same symptom — empty attribute in Merchant Center — but the fix is different at each one. The first four hops are where almost every bug lives.
Seven causes ranked by frequency
Cause 1: The metafield is on the product, but the mapping reads from the variant
Shopify has two separate metafield owner types for product data:
- Product-level metafield: attached to the product object. One value per product, shared across all variants.
- Variant-level metafield: attached to the variant object. One value per variant.
Google's color, size, gtin, and mpn attributes are all variant-scoped in any catalog with variants. If your products have variants and you stored color in a product-level metafield, the mapping has nothing to read at the variant level and submits empty.
How to tell which level you have:
In the Shopify admin, open a product, scroll to the Metafields section at the bottom of the page. If the metafield appears below the product description, it's product-level. If you scroll into a variant card and the metafield appears under that variant's details, it's variant-level.
The fix:
- If your products have variants: delete the product-level metafield and recreate it at the variant level under Settings > Custom data > Variants. Then re-populate values per variant.
- If your products have no variants: the product-level metafield is correct, and the issue is elsewhere on this list.
There's no clean automated way to copy product-level values to variants in bulk through the admin UI. The fastest path is a bulk operation via the Shopify GraphQL Admin API that reads the product-level value and writes it to each variant. For a one-time migration, expect to write a 50-line script; for ongoing data, restructure the source so values land at the variant level natively.
Cause 2: The metafield type is list.* or metaobject_reference instead of a scalar
Shopify metafield types include:
- Scalar types:
single_line_text_field,multi_line_text_field,number_integer,number_decimal,boolean,date,url - List types:
list.single_line_text_field,list.color,list.metaobject_reference - Reference types:
metaobject_reference,mixed_reference,product_reference,variant_reference,collection_reference,file_reference
The Shopify Google channel and most feed tools were built for scalar types. List types and reference types serialize as JSON arrays or as object IDs that the feed pipeline doesn't know how to dereference.
A common mistake: defining custom.color as list.color because you want to support multi-color products, then finding nothing comes through. The list serializes as ["red", "blue"] and the feed tool either submits that literal string (which Google rejects as invalid_color) or drops it entirely.
The fix:
- For multi-color products: redefine the metafield as
single_line_text_fieldand store a comma-separated string ("red, blue"). Google'scolorattribute officially accepts a slash-separated multi-value: "red/blue". Pick one delimiter and stick with it. - For metaobject references: dereference the metaobject in your feed-generation step. Most feed tools require you to configure a "resolve metaobject" step or expose the metaobject's individual fields as scalar metafields.
Shopify's Custom data documentation covers the type system in detail.
Cause 3: The metafield definition wasn't pinned when the product was edited
This one is sneaky. Shopify has a "pinned definitions" concept: a metafield definition only appears on the product edit page if it's pinned. If you defined custom.color after some products were already created and never pinned the definition, those products' edit pages don't show the field, and editors can't populate it through the admin UI.
The values that do exist (set via API or imported via CSV) still work. But if your team was supposed to manually fill in color for the holiday catalog and the definition wasn't pinned, none of those values were saved.
How to check:
- Settings > Custom data > Products (or Variants)
- Click the metafield definition
- Look for the "Pin" toggle in the upper right
- If it's not pinned, pin it now
After pinning, your team can populate the field on existing products through the admin UI. Existing values from the API or CSV are not affected; only the manual edit path needed the pin.
Cause 4: The stored value contains characters Google strips
Some metafield values look populated in Shopify but parse as empty in Google's pipeline. Common culprits:
- HTML entities. A
custom.colorvalue of&Red(because the source got HTML-encoded twice) decodes back to&Red, then toRed, with intermediate steps possibly losing it. - Zero-width spaces and other invisible Unicode. Pasted from a Word document, these survive in Shopify but get stripped by Google's normalizer.
- Emoji. Shopify allows emoji in metafield values; Google's
color,size,material,gender, andage_groupparsers strip them and may end up with an empty string if the value was just an emoji. - Smart quotes and typographic punctuation. Auto-generated quotes from Word or Pages survive in Shopify but can corrupt some feed-tool exports.
Test it: in the Shopify admin, view the metafield value. Open the browser console and run JSON.stringify(value). If the result contains (zero-width space), (non-breaking space), or escape sequences other than what you typed, the value is dirty.
The fix: normalize values on the source side. A bulk update script that strips zero-width chars, decodes HTML entities, and trims whitespace catches the common cases.
Cause 5: The Google channel sync hasn't run yet
Shopify's native Google channel doesn't sync in real time. The default sync cadence is roughly every 24 hours, with the exact timing varying by account. A metafield change you made an hour ago may not have hit the next sync window.
How to check:
- Open the Google channel app in Shopify
- Look for "Last synced" or "Last update" — the timestamp tells you the cutoff
- Compare to when you saved the metafield change
If the metafield was saved after the last sync, you haven't waited long enough. Force a sync by editing any product (even a no-op edit, like saving without changes) to trigger a queued sync, or wait the full 24 hours.
For third-party feed tools, the cadence varies:
- DataFeedWatch: configurable, default daily
- Channable: configurable, default hourly to daily depending on plan
- SnowPipe: on-demand or scheduled by the catalog manager
- BigCommerce's own GMC integration: roughly every 6 hours
Cause 6: The feed tool only fetches product-level data
A real failure mode I've debugged repeatedly: a feed tool that fetches products from the Shopify Admin API but doesn't separately fetch variants and the variants' metafields. The product-level metafields come through; variant-level ones don't.
Variant-level metafields need an explicit productVariant.metafields query against the GraphQL Admin API:
{
productVariant(id: "gid://shopify/ProductVariant/123") {
id
metafields(first: 50) {
edges {
node { namespace key value type }
}
}
}
}
If your feed tool returns only product-level metafields in its preview, that's the symptom. The fix is either to switch tools or to escalate with the tool's support — most modern feed tools support variant metafields, but configuration may not be on by default.
For Shopify's native Google channel, variant metafields are supported but the mapping UI is per-attribute. Make sure every variant-scoped attribute (color, size, gtin, mpn) has its mapping configured against a variant metafield, not a product metafield.
Cause 7: Namespace mismatch (custom.color vs mm-google-shopping.color)
Shopify has multiple metafield namespaces. The ones that matter for GMC:
custom.*— your own definitionsmm-google-shopping.*— installed by the (deprecated) Shopify Google Shopping appapp--*— installed by various third-party feed apps
A surprising number of stores have both custom.color and mm-google-shopping.color populated, with different values. The Google channel reads one; your feed tool reads the other.
Find all your namespaces:
In the admin, Settings > Custom data > Products lists every namespace with at least one definition. Or via API:
{
shop {
productMetafields: metafieldDefinitions(first: 250, ownerType: PRODUCT) {
edges { node { namespace key name type { name } } }
}
}
}
If you find duplicate definitions across namespaces:
- Pick one canonical namespace (
custom.*is the safest) - Confirm your feed tool and Google channel both point at the canonical namespace
- Either delete the duplicates or copy their values into the canonical one
A note on deprecation: Shopify deprecated the original "Google Shopping" app in favor of "Google & YouTube." If you have mm-google-shopping.* metafields, they're remnants from the old app and won't update automatically. Migrate values or remove the old metafields.
How to verify the fix
After making changes:
1. Force a fresh sync. Either edit a product to trigger a sync, or use your feed tool's "Sync now" button. Wait 1 to 24 hours depending on the tool's cadence.
2. Check the actual feed output, not just the Merchant Center UI. Most feed tools let you export the current feed as CSV or view the API payload that was last submitted. Find the affected product and confirm the attribute is now populated. If the feed shows a value but Merchant Center doesn't, the problem is between the feed tool and Google (likely caching or a mapping rule on Google's side).
3. Use Merchant Center's "Edit product" view. Open a single fixed product in Merchant Center, click "Edit," and look at the attribute. If it shows the new value, the fix worked. If it shows the old (empty) value, the feed submission hasn't been processed yet.
4. Cross-check the GraphQL response. Run a direct query against the Shopify GraphQL Admin API for one of the affected products and confirm the metafield value is there. If GraphQL returns an empty value, the issue is in Shopify, not downstream. If GraphQL returns the value but it doesn't reach Google, the issue is in the feed tool or the channel.
What not to do
- Don't add cache-busting modifications to push values through. Editing every product's title to add a space and then removing it does trigger a sync, but it also resets the review clock on every product.
- Don't recreate metafield definitions in a new namespace to "force" the sync. That creates more duplicate-namespace problems (Cause 7) and orphans existing values.
- Don't assume a value that displays in the admin is also being sent to Google. Admin display and feed serialization are different code paths. Always verify by inspecting the actual feed output.
- Don't trust the Google channel app's "synced" state without verifying values in Merchant Center. The app reports "synced" when the API call succeeded, not when Google validated the value.
How SnowPipe handles this
SnowPipe syncs Shopify catalogs to Google Merchant Center via the Merchant API v1. Four design choices in SnowPipe directly address the metafield-sync failure modes above:
Variant-aware metafield discovery. On connection setup, SnowPipe queries both product-level and variant-level metafields from the Shopify GraphQL Admin API. The catalog manager sees the full namespace + key + owner type list, with a clear distinction between product-scoped and variant-scoped fields. Cause 1 and Cause 6 are caught before mapping is configured.
Type-aware serialization. SnowPipe inspects each metafield's declared type. Scalar types serialize directly; list types serialize as Google-compatible delimited strings; metaobject references are resolved through one extra fetch. List and metaobject fields don't silently disappear (Cause 2).
Value normalization on read. Before any metafield reaches the outbound API call, SnowPipe normalizes the string: decodes HTML entities, strips zero-width Unicode, normalizes to NFC, and trims whitespace. The "looks populated but parses as empty" failure mode (Cause 4) is suppressed by default.
Manual sync trigger. Instead of waiting for a scheduled sync, you can trigger a refresh on any GMC connection from the Products tab. Useful for verifying a metafield change is propagating without waiting the full 24-hour cycle (Cause 5).
You can see per-attribute coverage, namespace breakdown, and per-product values in the Products tab of every GMC connection, with deep links back to the Shopify admin for fixes.
Summary
A Shopify metafield that doesn't sync to GMC usually fails at one of five hops: product-vs-variant scope mismatch, wrong metafield type, unpinned definition, dirty value, missed sync window, feed-tool blindspot on variants, or namespace duplication. The fix at each hop is different. Verify with a direct GraphQL query first to confirm the value exists in Shopify, then check your feed tool's output before blaming Google. Re-review after a confirmed feed submission takes 24 to 72 hours.
Tired of fighting Shopify-to-GMC sync issues one metafield at a time?
Try SnowPipe free — connect your Shopify store and get variant-aware metafield mapping plus accurate Google syncs in minutes. Or, book a 15-min demo and I'll walk you through your specific setup.