Shopify, Google Shopping and Product Variants: How to Fix your Feed

The Google Shopping Feed app by Shopify is a great way to publish your products to Google Merchant center. However, if you are a clothing retailer with multiple variants of the same product in different colors the Shopify app will only publish your first variant.

only-first-product-published

While we wait for a fix to be delivered, here is an alternative way to submit your own product feeds to Google Shopping, including all your variants:

  1. Install and upload your feed using the Shopify Google Shopping App
  2. Create a custom collection template that outputs your products as xml
  3. Assign the products you want to publish to your new xml collection template.
  4. Submit your new xml collection url to Google Merchant Center.

Step 1: Install Shopify’s Google Shopping App

Shopify’s app is an excellent tool for managing your Google Shopping product attributes, including custom labels, product categories, etc… The custom feed we are about to build will enhance Shopify’s base feed with extra variant information and customized titles. But the base app is still needed, as we will make use of the app’s metafields.

Step 2: Create the XML Collection Template

This step involves getting your hands dirty with code. If you are not a developer and have a low appetite for risk, consider asking a coder to do this step for you.

What we are doing here is creating a template, that when assigned to a collection, will cause that collection to be displayed as XML instead of HTML.

In your Shopify admin, go to:

  • Online Store > Themes
  • In the dotdotdotmenu and choose Edit HTML / CSS
  • Under Templates, choose Add a new Template
  • Choose collection from the drop down and name your template xml-product-feed

Paste the following code into your new template and click Save. (It is probably safer to copy and paste this code from github, as that will always be the most up to date version: Shopify xml Variant Shopping Feed)

IMPORTANT: Do not add any extra spaces before or after this code. Your very first line should be start with {% layout none %} and your very last line should be {% endpaginate %}

 

{% layout none %}<?xml version="1.0"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
{% paginate collection.products by 1000 %}
{% assign useSEOtitle = false %}
{% assign useSEOdescription = false %}
{% assign CountryCode = 'US' %}
{% if shop.currency == 'CAD' %}{% assign CountryCode = 'CA' %}{% endif %}
{% assign Color = "" %}
{% assign Size = "" %}
<channel>
<title>{{ shop.name }} {{ collection.title | strip_html | strip_newlines | replace: '&', '&amp;' | replace }}</title>
	<link>{{ shop.url }}</link>
<description>{{ collection.description | strip_html | strip_newlines | replace: '&', '&amp;' }}</description>
{% for product in collection.products %} 
  {% assign GoogleProductCategory = product.metafields.google.google_product_type %}
  {% assign Gender = product.metafields.google.gender %}
  {% assign AgeGroup = product.metafields.google.age_group %}

  {% for variant in product.variants %}
    {% assign Color = "" %}
    {% assign Size = "" %}
    {% for option in product.options %}
  	{% if option == 'Color' %}{% capture Color %}{{ variant.options[forloop.index0] }}{% endcapture %}
  	{% elsif option == 'Size' %}{% capture Size %}{{ variant.options[forloop.index0]  }}{% endcapture %}
  	{% endif %}
  	{% endfor %}

    {% capture productTitle %}{{ product.vendor }} {{ product.title }}{% endcapture %}
    {% unless productTitle contains Color %}{% capture productTitle %}{{ productTitle }} {{ Color }}{% endcapture %}{% endunless %}
    {% if useSEOtitle and product.metafields.global.title_tag.size > 0 %}{% assign productTitle = product.metafields.global.title_tag %}{% endif %}
    {% assign productDescription = product.description %}
    {% if useSEOdescription and product.metafields.global.description_tag.size > 0 %}{% assign productDescription = product.metafields.global.description_tag %}{% endif %}

<item>
<title>{{ productTitle | strip_html | replace: '&', '&amp;' }}</title>
	<link>{{ shop.url }}{{ variant.url }}</link>
<description>{{ productDescription | strip_html | strip_newlines | replace: '&', '&amp;' }}</description>
<g:google_product_category>{{ GoogleProductCategory | replace: '&', '&amp;'  }}</g:google_product_category>
<g:item_group_id>shopify_{{ CountryCode }}_{{ product.id }}</g:item_group_id>
<g:id>shopify_{{ CountryCode }}_{{ product.id }}_{{ variant.id }}</g:id>
<g:condition>new</g:condition>
<g:price>{{ variant.price | money_without_currency }} {{ shop.currency }}</g:price>
<g:availability>{% if variant.available %}in stock{% else %}out of stock{% endif %}</g:availability>
<g:image_link>http:{% if variant.image.src %}{{ variant.image.src | product_img_url: 'grande' }}{% else %}{{ product.featured_image.src | product_img_url: 'grande' }}{% endif %}</g:image_link>
<g:gtin>{{ variant.barcode }}</g:gtin>
<g:brand>{{ product.vendor }}</g:brand>
<g:mpn>{{ variant.sku }}</g:mpn>
<g:product_type>{{ product.type }}</g:product_type>
<g:age_group>{{ AgeGroup }}</g:age_group>
{% unless Color == "" %}<g:color>{{ Color | strip_html | strip_newlines | replace: '&', '&amp;' }}</g:color>{% endunless %}
{% unless Size == "" %}<g:size>{{ Size | strip_html | strip_newlines | replace: '&', '&amp;' }}</g:size><g:size_system>US</g:size_system>{% endunless %}
<g:gender>{{ Gender }}</g:gender>
<g:custom_label_0>{{ product.metafields.google.custom_label_0 }}</g:custom_label_0>
<g:custom_label_1>{{ product.metafields.google.custom_label_1 }}</g:custom_label_1>
<g:custom_label_2>{{ product.metafields.google.custom_label_2 }}</g:custom_label_2>
<g:custom_label_3>{{ product.metafields.google.custom_label_3 }}</g:custom_label_3>
<g:custom_label_4>{{ product.metafields.google.custom_label_4 }}</g:custom_label_4>

<g:shipping_weight>{{ variant.weight | weight_with_unit }}</g:shipping_weight>
</item>

{% endfor %}
{% endfor %}
</channel>
</rss>
{% endpaginate %}

or Download from Github: Shopify xml Variant Shopping Feed

Step 3: Assign products to your xml Collection.

You should now have a new XML Template created. This is just the template that defines how your collection will be displayed on your site. We now need to assign products to this template so we can submit the feed to google.

This involves creating a new product collection, and choosing the xml-product-feed as the template to use:

  • Go to Products > Collections
  • Click the Add Collection button
  • Enter a name for your new collection. I recommend XML Google Shopping Feed – All if you want a single feed for all your products or XML Google Shopping Feed – Shoes if you want this feed to contain your shoe products (or other product type).
  • Add products you want published as part of this collection feed. (either manually or via dynamic rules)
  • Click Save.

Preview the collection to make sure it works. You should just see a bunch of unformatted text on the screen. If you do a “view source” in your browser, you should now see the formatted XML.

Make sure you copy the url of this collection, as you will need to submit this url to Google Merchant center.

Step 4: Submit your feed to Google Merchant

Make sure you have your xml collection url open from step 3 above.

  • Log into Google Merchant Center or create an account if you do not have one.
  • Go to Feeds and click the +Feed button to create a new feed.
  • Mode: Choose Standard or Test (recommended that you choose Test until you are sure the feed is correct)
  • Feed type: Products
  • Select your target country & language. If you have multiple target countries, you need to submit a separate feed for each.
  • Enter a descriptive name for your feed. eg: Shopify XML Feed – Shoes
  • Choose Scheduled Fetches as your input method (recommend daily)
  • Enter your collection url in the File URL field, and the collection’s filename in the name field (eg: name=google-shopping-feed-shoes and url=http://mystore.myshopify.com/collections/google-shopping-feed-shoes)
  • Save and click the Fetch Now button to download the feed. Wait a few minutes for the feed to complete.
  • Fix errors: If there are errors, Google Merchant Center will tell you in a few minutes. Go back and fix any errors, re-fetch, and keep doing so until the file is error free.

If you have more than 1000 variants, you will need to submit multiple feeds with the ?page=x querystring appended as so:

Troubleshooting

If you receive any errors, the best way to troubleshoot them is to open the the collection / feed url in your browser and do a view source. Then navigate to the line & character of the error to investigate further

Common Errors

  • Improperly formatted XML Error on Line 1: This is usually because your template has a blank line as it’s first line. Delete the blank line and make sure your template begins with {% layout none %} … exactly as in the code.
  • Improperly formatted XML Error on Line 1: The other cause of this error is that you forgot to choose the XML template for your Shopping Feed Url, and you are actually outputting HTML. Go to your collection in the Shopify Admin console and set the template correctly (at the bottom of the right hand column) 
  • Errors at Lines XXX: The xml file does not support & and > characters. These must be replaced by encoded versions &amp ; &gt ; or the feed will report errors.

(optional) Step 5: Exclude your feed collection from showing up on your store pages

If your store is setup to programatically display all your collections, then you will want to make sure your xml feed doesn’t show up. The exact way to do this will change depending on your theme, but generally you will want to have an “unless” statement within the loop that displays your collections:

{% unless collection.title contains "xml" %}
... your collection code ...
{% endunless %}

Customizing

If you have complex rules or customization that you want to apply to your feed, you have several options:

  • Use the Google Merchant Center “Feed Rules” tab to transform various values based on various conditions. This is very powerful!
  • Modify your collection template and add conditional statements based on product titles, tags, metafields, etc…
  • Create multiple collection templates with hard coded values
  • Create custom Feed Rules in Google Merchant Center
  • A combination of the above.

If you have more than 1000 variants, you will need to submit multiple feeds with the ?page=x querystring appended as so:


Related Posts & Resources

92 Comments

  1. Hi, I’ve tried to use the code but it throws an error. “Wrong number of arguments (given 1 expected 2..3)”. Do you know what am I missing? Thank you

    Like

    Reply

  2. Hi Alex,

    Great article; the first one I have found that starts to help me understand the trials and tribulations of feeds and Google Shopping! Whilst processing through your guide I actually felt I knew what I was doing (first time for everything!!).

    I have created the template and collection and set up the feed in Merchant Centre. However, when I process the file in Merchant Centre, it comes up with an error.

    Tracking through the output code for the collection, there is an “&” at the error point. This is created by google’s very own product category “Jewelry & Watches” – so how do I go about changing how the category is read in the output code? This product category is where all my products lie!

    I’m not sure you can do this from the template or from the collection code itself unless you know a way?

    Like

    Reply

    1. Hi Letty,

      If you download the most recent version of the code available here:
      https://github.com/Czarto/ShopifyScripts/blob/master/Templates/collection.xml-product-feed.liquid

      Your issue should be fixed. (I will update this post now with the latest code as well).

      Essentially you need to replace “&” with ” ” when outputting the Google Product category. This has been fixed in the latest version of the code.

      Let me know if you’re still having issues!

      Best

      Alex

      Like

      Reply

      1. Hi Alex,

        Yes this helped – thank you. I reloaded with the latest script but it produced the same error initially. What I was able to do though was locate the fault and transpose the updated code to fix the error.

        Kind Regards,

        Letty

        Like

  3. Thanks Alex, it is very strange, I have ticked the box ‘Tell Google to ignore product identifiers’ and when I look closely, the items that are being flagged up in merchant centre they aren’t even in my google shopping collection, so I am not too sure how they are being collected from my store.. I have another feed running through the app adrobot and that seems to be working, do you think there is some code I need to add in to XML feed to make it ignore the GTIN numbers?

    Like

    Reply

    1. Hi Isobel,

      Sorry for the very late reply.

      It looks like I need to add another property to the script that sets identifier_exists to FALSE for any products that do not have a GTIN.

      I will add it to the todo list.

      Alex

      Like

      Reply

  4. Hello again! Please ignore my query above I have worked it out! I now have a problem of the merchant centre asking me for GTIN’s but I do not have any as I produce the items myself. Do you know how I can over ride this?
    Thanks
    Isobel

    Like

    Reply

    1. Hi Isobel,

      Try this: In the Google Shopping app, there is a checkbox that says: “Tell Google to ignore product identifiers”. Try checking this for all your products and resubmit them.

      Let me know if that helps.

      Best,

      Alex

      Like

      Reply

  5. Hi,
    Thank you for the great article. I am having a few problems getting the feed up and running. I have inserted the code and made a collection but the merchant centre is saying there is an XML formatting error:

    1 feed error

    XML formatting error1 error
    Our system encountered an error when processing your data feed. Learn more
    Examples:
    Line Nr. Column Nr.
    2
    22

    Do you know how I can rectify this problem?

    Isobel

    Like

    Reply

      1. Hi Tarek,

        Sorry for the late reply.

        The best way to start troubleshooting this is to open your feed’s url in a web browser and do a “view source”, and see what text/characters are at the line + column where the error occurred.

        Best,

        Alex

        Like

  6. Replying again as I finally got access to my clients google merchant account. The feed that we’re trying to push there from Shopify actually is not showing up there. It seems Google Shopping error in the app is causing it not to publish to Google Merchant. So I can’t get it in there to make the column adjustments. Any suggestions? Thanks again.

    Like

    Reply

    1. Hi,

      For setting the XML template, you should have access to it in:

      Shopify Admin > Products > Collections > Open a Collection > Right Hand Column underneath the Collection Image –> “Theme Templates”.

      But maybe you are right that newer themes with sections don’t show it here? Let me know…

      If the Google Shopping App is throwing an error and is not publishing, you can still publish the feed directly using the XML template. It should still grab all the meta-data from the Google Shopping app (even if the app didnt’ publish anything).

      Alex

      Like

      Reply

      1. I don’t believe the sectioned theme is causing the issue – running one here with no problems, and I’m using alternate templates for collections. One thing to note is that if you don’t choose “collection” at the dialog box prompt “Create a new template for…” when creating a new template (Edit HTML/CSS -> Add a new template) the template won’t be created with the correct file name, and won’t be visible in the template list on a collection page.

        After you create a template, you should be able to see it in the template file list (on the page you got to by choosing “Edit HTML/CSS” from your theme page) with the name “collection..liquid” The “collection.” prefix on the file name is what causes it to be shown in the collection template dropdown.

        Not sure if this is applicable to the problem you’re seeing, but it was a self-inflicted issue I tripped over on the way to setting up my feed.

        Rick

        Liked by 1 person

      2. *sigh* WordPress removes text in angle brackets from comments. Where my last post has the template file name ““collection..liquid” I had included “your template name” in brackets between the dots. For example, the filename you see would be “collection.xml-product-feed.liquid” if you followed Alex’s suggestion. Apologies for the typo.

        Like

      3. Hey Guys. Again sorry for the delayed response. Ok ultimate bonehead move on my part. I was working on an inactive theme to make my changes so when I went to set my collection template it wasn’t showing up. Once I moved the changes to the live theme I saw the template option. Really sorry to have wasted your time on that. I’m a dummy :).
        Can I use the same feed I make for google within Facebook to set up a product catalog? It seems like it but figured I’d ask. Thanks again!

        Like

  7. Hey Alex. This has been a great read. Thanks for creating this tutorial.
    I had a quick question. My client sells bras, according to Google SIZES for underwear should be in the format like “36 B”, but my client has their store set up with 3 variants for BAND SIZE, CUP SIZE and COLOR. So they split up the Size into Band and Cup. When I try to use Google Shopping it throws an error that it’s missing “Size”. I thought to maybe add a 4th variant of “Size” with the correct google friendly value but I can only have 3 variant options on a product.

    Can I still use Google Shopping but generate a custom XML feed to submit? Or will it not work if Google Shopping is throwing an error?

    Thanks!

    Dave

    Liked by 1 person

    Reply

    1. Hi Dave,

      I think the products will still publish to merchant center but will just be in an error state until the size issue is resolved.

      I think the XML file is a great way to resolve this. Either by adding custom code to the xml template to combine Band and Cup into the size field, or what might be cleaner, is to do this combination on the Google merchant side of things (I forget the exact name of this option, but when uploading a new feed you have the choice to dynamically create new columns based on existing columns in your feed)

      Hope this helps.

      Best,
      Alex

      Like

      Reply

      1. Hey Alex. So Sorry for the late reply. I had not checked off the notify me box and was waiting on client to work on this so it had been sidelined for a bit. Anyway. I’m getting back on track now….

        I’m going to give the column concatenation a try for sure! that sounds cleaner and easier. Thanks for the tip!

        Also, dumb question… following your directions in the post, I don’t see where I’d choose the XML template on the collections page. I figured it would be obvious but I don’t have such a choice. You also don’t mention the selection of a template on that page but from my digging around I suspect its supposed to be there somewhere. Weird.

        Thanks again!

        Like

      2. Hey again, So I figured out the answer to my dumb question above. The reason I’m not seeing a template option on the collection page I think is because I’m using a newer “sectioned” theme. So the setup of a feed would be different I believe. Still trying to figure it all out but just thought I’d post here to help anyone else that may find there way here and was wondering about that. Thanks again.

        Liked by 1 person

  8. Hi Alex!

    Thanks for all the work on this. It’s refreshing to see succinct documentation and sample code!

    I have questions about playing nicely with the current state of Shopify’s Google Shopping app. From what I can see, the app does now create variants, at least for me. (I’m varying apparel size and material only, not color.) Google sees the variant id and item_group_id in the Shopify API feed data. Some of data for the individual variants comes from the product, rather than the variant – for instance the MPN is always the product-level MPN, and the individual variant SKU (which I’d like to use as the variant MPN) doesn’t make it to the variant data. I’ve tried poking values into variant metafields, in the hope that someone at Shopify implemented the same metafield-handling code for variants as they did for products, but no joy.

    Given that Shopify is creating items in the data with the same ids and group ids as a feed that I can supply, how do the two data sources interact?

    The behavior I’ve obseverd, based a tiny amount of testing, is that they step on the same data fields, and the last update wins.

    If the two-feed strategy is working despite that, I’d guess that Shopify will only update the entire collection of data on an item when I explicitly publish it, and only do inventory feed updates to google for inventory and price changes, so the rest of the data isn’t affected. (“Shopify will only update the entire collection of data on an item when I explicitly publish it” is a critical assumption. Is there is something I can do inadvertently in Shopify that will trigger a full feed update to google? I’d dearly like to know about it. 🙂

    So the correct operational sequence is 1) add a new product to the google shopping api collection in shopify, 2) publish the new items in the Shopify google app, and 3) manually fetch my XML feed to fix the data in the new items. (Or wait for 2 & 3 to happen as scheduled, and put up with bad data in the new products for less than a day.)

    Are my guesses accurate?

    Thanks!

    Rick

    Like

    Reply

    1. Hi Rick,

      Sorry for the delayed response.

      Yes, both sources (Shopify App + Manual Feed) will overwrite / augment the data stored in Google Merchant. The steps you mention are exactly as I usually do them:

      1. Add new product to the shopping api collection in Shopify (and update any meta fields)
      2. Publish in the Shopify app
      3. Set a schedule to fetch the xml feed daily to overwrite/augment any changes that may have been pushed by the Shopping API.

      I don’t have any special insights into what’s going on in Shopify behind the scenes, but this seems to work well for me.

      Best,

      Alex

      Like

      Reply

      1. Thanks for the follow-up Alex!

        Your XML template idea turns out to be the key idea in this – we ended up putting all our info in the template, and deleting the Shopify app.

        The major issue for us is that Shopify doesn’t push the variant SKU into the google feed as the variant MPN, but uses the same product SKU for all variants. We’re a manufacturer with several hundred products, and we have unique SKUs for each product variant. We don’t use UPC codes, as we don’t sell through mass-market retail channels. Google allows us the combination of Brand and variant MPN to be used instead of barcode/UPC. (Overloading the barcode field in shopify doesn’t work, as Google is looking for UPC/EAN etc values there, and will disallow non-checksum-able data in the field.)

        In addition, Shopify uses its database ids for product and variants for variant keys, and to generate the item_group_id that links variants of a product. Having the shopify database ids showing up in our google feed (instead of our own sku and variant ids) means if we delete and recreate products in shopify, we interrupt product continuity in our google product and analytics data, as they have new ids in the feed.

        (And, there are a bunch of other data issues we wanted to fix, including generating google-safe titles, and correctly filling the product type field for google, which is very different than the common usage in Shopify.)

        After some head-scratching, we realized that the metafields set and used by Shopify for their app aren’t magic, and are just the values they use for their version of the feed. We co-opted some of them, created a few of our own, and use the values in the XML template. (We’re creating products using the Shopify admin API, so setting up the metafields is easier than by hand. 🙂

        The advantages we can see coming from a Shopify app, if it worked well, would be that it uses the google API for timely incremental updates as we change data in shopify, rather than a once-a-day feed, and that it should update availability and prices in real-time. However, those are would-be-nices rather than needs; google seems happy with our XML feed, and our page microdata is available when google pulls a product page, so I think once per day availability and pricing data in the XML feed are fine, too.

        Thanks again for your XML feed template; that was the seed idea for our implementation, and it’s working very well.

        Rick

        Liked by 1 person

    1. Hi Mitch,

      Currently the script loops through all your products, and for each product, loops through all it’s variants. The script does not output any specific record for just the product, instead it outputs one item per variant. I may be misunderstanding your question, but I believe it already does what you are asking?

      Alex

      Like

      Reply

  9. Hey Alex. Thanks for the great tutorial. I am using this script for the Google Product feed because of the single variant issue, however, Flexify seems to require the Google Shopping Feed app. First question, Flexify must be referring to the Google Shopping Feed app so does that mean it will also have the single variants issue? Second question, if so, is there a way to have Flexify refer to this XML feed instead?

    Like

    Reply

    1. Hi Tanner,

      I think if you use Flexify, you should be fine. I **believe** (but don’t know for sure) that Flexify probably only uses the Shopify app to set Google Product Categoy, Age, Gender, etc… My script does the same thing. Essentially I rely on the Shopify App’s interface to manage the product attributes, and then this feed will supplement the feed that the App submitted. (I believe Flexify does something similar, but do not know for sure).

      Best,

      Alex

      Like

      Reply

      1. Alex, thanks so much for the reply. So it sounds like the Google Shopping App actually writes to the database and then sends the data to Google Merchant Center via API. Is your script then *updating* the feed that Google Merchant Center receives from Google Shopping App? And if that’s the case, Flexify is still sourcing data directly from the Google Shopping App/database and doesn’t include the new information from your script.

        *Although* I have been testing out the Flexify feed in the Facebook Product Catalog and have not been receiving any errors on variants so I don’t think the Facebook Product Catalog cares the much about the extra info.

        So maybe it doesn’t matter? Unless you have more insight on this.

        Liked by 1 person

  10. Alex, I want to change some of my XML collections to show SEO ttile while others use product tiles. Can i copy the code and create a another collection file and use that for certain collections (by selecting the proper one in the collection setting)? Do you see any issues with it?

    Liked by 1 person

    Reply

  11. Hi Alex & Everyone,
    Anyone have a solution for as Google product reviews feed? There seem to be some Haddon Apps that have this but just want to feed so looking for a simple solution. Great if can create a XML reviews feed.
    Keen get this going so happy to test if any ideas?
    Thanks,
    Seán

    Like

    Reply

  12. Hi all,

    Just wanted to provide an update to my situation.

    For the record, I’m almost 100% certain the problem is on Shopify’s end. What I think occurred is that a bunch of people used the feed option with their Shopify-hosted website, and Google’s Merchant Center crawler bot just started getting filtered by Shopify’s own firewall, since a bot making hundreds or thousands of requests (to each person’s separate store, but if you’re hosted with Shopify, then everyone’s request is hitting the same server, theoretically) in the span of a couple minutes might be the sort of thing that gets classified as a potential DDOS attempt by firewall software.

    I spoke with Shopify’s support chat last Friday. I wasn’t very hopeful after speaking with the person in the chat, but ultimately it looks like the technical team made the change I requested, i.e. for Shopify to stop filtering/blocking Google Merchant Center’s crawler bot.

    My feed is working now, for the past few days. No more 403 errors for me.

    Liked by 1 person

    Reply

  13. I have started to get 403 error code (Xenon connected to the source server to transfer a file, but couldn’t find the file) on ALL my feeds. started happening few days ago so feeds are not updating. I have raised the issue with google. Any insight as to why it may be happening? Is it an issue on my end or google’s end?

    Like

    Reply

    1. Hi Asif,

      It seems a few more people are having the same issues (see Sam’s and Dan F’s comments above yours). I don’t know what the issue would be (things are working fine on my end by (1) I’m not using paging and (2) I’m on Shopify Plus — not sure if that’s a factor or not).

      Let me know (or post here) one you hear back from Google or Shopify with a cause or solution.

      Best,

      Alex

      Like

      Reply

  14. Hi dan – I’ve been using this feed system for close to a year now and am just encountering the same problem as you. My feeds are paginated (8 pages, 400 products each). Weirdly pages 1-4 load fine in merchant center, but pages 5-8 produce the 403 error. I’ve escelated the issue with both google and shopify, but have yet to get a response that solves the problem or even fully identifies where the problem is coming from. If I make any progress, I’ll post it here.

    Sam

    Like

    Reply

  15. Hi Alex,

    First off, thanks for the great article and solution.

    I am having difficulty importing the product feed to Merchant Center. I did everything in the instructions (including setting the collection template to collection.xml-product-feed), but when I try to fetch the feed in MC, it returns a 403 error (Forbidden).

    Just like in the instructions, my ‘File name’ is ‘xml-google-shopping-feed-all’ and my ‘File URL’ is ‘https://myshopifystore.com/collections/xml-google-shopping-feed-all’. I can access the URL just fine, just like in the instructions, and viewing source shows the XML data, as expected.

    Creating the Product Feed in Merchant Center: https://i.imgur.com/wwViNNI.png
    After clicking ‘Fetch Now’ in Merchant Center: https://i.imgur.com/jYDQcvV.png

    Can anyone help me with this? I would really appreciate it.

    Thanks,
    Dan F

    Like

    Reply

    1. Hi Dan,

      I’ve heard a few people having similar problems to you, but intermittently (sometimes it works, sometimes it doesn’t), and generally when paging multiple pages of a feed. No solution so far, but I will post something here as soon as I know something.

      What plan are you on with Shopify? (It may be related to API limits or something)

      Alex

      Like

      Reply

      1. Alex,

        Thanks for the reply!!

        Well, I think I can safely say that my problem isn’t intermittent. I’ve tried and retried probably 15 times over the last couple days. I also only have 1 page of products (I tested this by doing the page=2 and seeing that it returned nothing).

        I did some testing and it seems to me that Shopify is blocking the Google crawler. My testing consisted of trying different URLs on my Shopify store, a URL on a random Shopify store from the internet, and a random URL from a non-Shopify website. The testing revealed that any URL to my Shopify store returned a 403, the URL from someone else’s store returned a 403, and the non-Shopify URL returned an HTML page (not parseable, obviously) as expected.

        To your question, I have the (normal) Shopify plan. Like I said, *I* can access the feed just fine. It just seems like Google (Merchant Center) is unable to due to some sort of firewall or IP address exclusion.

        I’ve posted a similar question on Shopify’s forums, so if there is a solution I’ll definitely share it with you to share with your readers.

        Even though we couldn’t figure this out, thanks again for the quick response — I really appreciate it!

        Dan

        Like

  16. What does Paginate by 1000 does? My feeds are as much as 2200 products and have been uploaded successfully. Is it possible that only 1000 products are being shown in google adds, though google merchant shows all products uploaded successfully?

    Like

    Reply

  17. Hi Alex, thanks a bunch for your help. It was pretty straight-forward even for a non-tech like myself. The only thing I’m struggling with is hiding the collection. Below is where I placed the code. Could you tell me where I misplaced it? (XML is capitalized in the title) Thanks.

    {% if settings.collection_sidebar %}
    {% include ‘sidebar’ %}

    {% else %}

    {% endif %}

    {% if settings.display_collection_title %}
    {% unless collection.title contains “XML” %}
    {{ collection.title }}
    {% endunless %}
    {% endif %}

    {% if collection.description != blank %}

    {{ collection.description }}

    {% endif %}

    {% if collection.products.size == 0 %}

    {{ ‘collections.general.no_matches’ | t }}

    {% else %}
    {% assign products = collection.products %}
    {% assign products_per_row = settings.products_per_row %}
    {% include ‘product-loop’ with settings.collection_sidebar %}
    {% endif %}

    {% include ‘pagination’ with settings.collection_sidebar %}

    {% endpaginate %}

    Like

    Reply

    1. Hi Tracy,

      I believe you would want to edit the “sidebar” snippet, and not the code above.

      The code above is what displays the products in your collection, while the sidebar snippet is what displays the links to all your collections.

      Let me know if that helps!

      Like

      Reply

      1. Hey Alex,

        Yes placing it in the sidebar snippet worked! I also changed tag to col.handle and “xml” to ‘xml’. So it now reads
        {% unless col.handle contains ‘xml’ %}

        Thanks again.

        Like

  18. Alex, My google shopping is till not showing the variants in the actual results. It shows the feed approved in google merchant but I have not see any result with a variant info shown in actual search results. Also note that my theme/shopify does not create a unique URL for variants. This is something recommended by google for variants so not sure how it effects the search results. Also my images have a logo watermark so not sure either if this has any negative effects. Please let me know if you have any insights as to why my variants are not showing up in search results.

    Like

    Reply

    1. Hi Asif,

      I think you definitely need to enable links to specific product variants (with ?variant=123456789 ) to keep google happy (but I’m not sure if this is your problem specifically, but it’s definitely something you should look at fixing)

      Otherwise, I unfortunately do not have any more insightful insights to help you with this.

      Sorry. 😦

      Alex

      Like

      Reply

  19. Hi Adam,

    I believe what is happening is that the Colour variant is not being reset between products. I’ve updated the code to handle this case.

    Try this:

    {% for variant in product.variants %}
    {% assign Colour = “” %}
    {% assign Size = “” %}
    {% for option in product.options %}
    {% if option == ‘Colour’ %}{% capture Colour %}{{ variant.options[forloop.index0] }}{% endcapture %}
    {% elsif option == ‘Size’ %}{% capture Size %}{{ variant.options[forloop.index0] }}{% endcapture %}
    {% endif %}
    {% endfor %}

    Like

    Reply

  20. Hi Alex,
    What a great post, thank you!
    I was hoping for a little help, everything seems to be working fine, except the colour option, being in the UK I changed the code in your script from “color” to “colour” and that seems to work, but for some random products where there is no colour option it is populating this with a random colour from another product.

    For example we sell pet products and have items like “pink dog collar” which obviously would not have a colour variation so it seems to be using a random colour resulting in “pink dog collar blue” etc.
    I have looked through the code and cant seem to find the issue, should it not be displaying the size option if no colour option is available?
    Any ideas would be most appreciated.

    This is the current section of code i believe relates to this…

    {% for variant in product.variants %}
    {% for option in product.options %}
    {% if option == ‘Colour’ %}{% capture Colour %}{{ variant.options[forloop.index0] }}{% endcapture %}
    {% elsif option == ‘Size’ %}{% capture Size %}{{ variant.options[forloop.index0] }}{% endcapture %}
    {% endif %}
    {% endfor %}

    Like

    Reply

  21. Hi Alex,

    I saw that my brand name was getting added to the front of my product title, so removed Vendor code from the Item part of script. Looks like you did that too for the default script. The Color also appears to have been removed from what I copied before, so I removed that too.

    Aside from not having my brand/store appear redundantly in the Google Shopping title, my goal was to have Google aggregate all my variant product reviews under one parent listing. The benefit is that the aggregate number of ratings will be much higher than for each individual size/color variant. Do you know if this is possible, or will Google keep showing the variants as separate products because each has a unique MPN?

    One other thing to note, the script above has a misspelling that may have an effect: “productDescrition”

    Thank you for any suggestions with how to get Google Shopping to aggregate all variant reviews under the parent product.

    Best,
    Dave

    Like

    Reply

    1. Hi Dave,

      I’ve fixed the typo — thanks for pointing it out.

      For your other question, I unfortunately do not know the answer. We already include the item_group_id in the feed, so that is a clear indication to Google that all these variants belong to the same product. I suspect that this is fully controlled by Google and that we do not have much influence on aggregating all product reviews. At some point I will look deeper into Google Product review feeds, but for now I unfortunately do not have much experience with them.

      Best,

      Alex

      Like

      Reply

    1. Hi Cindy,

      Try reducing the number of products you display per page feed by changing Line 3: “paginate by 1000” to something like “paginate by 200”. You are likely hitting some sort of resource limit for your account.

      Like

      Reply

      1. Hi Alex! That works! I changed it to paginate by 500 instead … does this mean that “?page=1” will send products 1-500?

        Like

      2. Also how do I switch it from test to Standard once I’m sure the feed is correct? Thank you for such an awesome post!

        Like

      3. Hi Alex,

        Changed it to paginate by 500 and submitted separate feeds for 0-500, 501-1000 etc but am getting an error message about items uploaded through multiple feeds!

        “641 item warnings – These are warnings for recommended and optional attributes, but will not affect your data upload Items uploaded through multiple feeds: The item was previously uploaded using a different feed. Please make sure to use the same feed for all uploads of a given item.”

        Cindy

        Like

      4. Hi Cindy,

        I unfortunately do not have an answer for you as I actually don’t use paginated feeds and so haven’t encountered this problem. I would first double check that the same page is not submitted multiple times. And then I would look at what products are being duplicated and do a view source on your feed URL to see if you are indeed submitting those products twice.

        Sorry that I can’t be more helpful.

        Good luck!

        Like

  22. Alex, My google merchant account is showing 20,000 products approved but the actual ad is not showing the variants. There are no issues with the feed. One thing i noticed that my options are not Color and Size and they vary based on the type of product. Currently i am not using SEO title since my product title and descriptions are well written. 1) How can i make sure all the variants actually show up in add? 2) Do i need to edit the code to put the actual option name i am using? 3) Can you please provide a template that i can use to add different option names? These will be more 20 different types so not sure what is the best way.

    Like

    Reply

    1. Hi Asif,

      I believe adding the different option values to your Title should do the trick. Here is one way to do it (code untested):

      On line 26 (roughly) change the following line:

      {% capture productTitle %}{{ product.vendor }} {{ product.title }} {{ Color }}{% endcapture %}

      to

      {% capture productTitle %}{{ product.vendor }} {{ product.title }} {{ variant.options[0] }} {{ variant.options[1] }} {{ variant.options[2] }}{% endcapture %}

      This **should** write out the values of all three options (and just leave blank if that option is not set).

      Let me know if it works.

      Good luck!
      Alex

      Like

      Reply

  23. Thanks for the quick response. I tried feed with all the products and it gave me error. After trial and error i figured out that it it taking up to 2500 products without issues. I subdivided my feed into separate feed no more than 2500 products each and it all fetched successfully. Currently it is in “pending” state and slowly being released. I have received “XML Formating Error” on one feed and trying to figure out what is causing it. Also have occasional pricing issues, description issues, image issues that i will have to clean up. I also realized that the XML collection is not showing up in my regular collection so that is no longer an issue.
    As for using the product title or SEO title, what is the best practice? Currently It is front loading the brand, followed by product title in google shopping result.
    Thanks for this wonderful post. Hopefully it all works out. My store is B2B ecommerce and google shopping is 50% of the traffic.

    Like

    Reply

    1. Hi Asif,

      Happy to help! 🙂

      XML formatting issues are often related to special characters in your title or description.

      For product Title, in **general** you should probably go with [Brand] + [Product] + [Color/Variant], but if this doesn’t make sense for you, then you can either change the convention directly in your xml template code, or just use the SEO Title is you want something very specific.

      Good luck!

      Like

      Reply

  24. Alex, This is a great post and I am glad I found it. Been frustrated with google shopping lately. I followed the instructions however I have 2000 products on my initial feed. I did not do the multiple page url and google merchant successfully imported 1934 products. What am i missing? This was just a test run for me as I plan to add 20,000 products eventually.
    After creating a feed, do I need to edit my ad campaign in google adwords or it will automatically pick the custom labels that I am using in the already running google shopping campaign.

    Also, my theme shows every thing in a collection with /Collections/All. I did not completely understood on how I can prevent it from showing on the page. Can you please elaborate on where the else code needs to be inserted.

    One last question, how can we prevent the google duplicate content penalty since we effectively have duplicate of entire product line in the XML collection. Can we no index it?

    Like

    Reply

    1. Hi Asif,

      RE: Only 1934 products imported
      It is possible that you are hitting some sort of API limit with Shopify? Not sure about what could be happening here. Did you check to see if there were any products that were not imported due to some error perhaps?

      RE: Modifying Adwords
      You shouldn’t need to update your current adwords campaign. It *should* just pickup the labels and run smoothly. But let me know if it doesn’t for whatever reason.

      RE: Hiding the XML Collection
      I’m not 100% if I understand the question correctly, but if you want to hide your XML Collection from showing, you need to find the place in your code where you are displaying all your collections and exclude it there. If you can clarify more what you are seeing I may be able to give you more details.

      RE: Duplicate Content
      I don’t think there’s any risk of this being flagged as duplicate content. It’s an XML file, and so Google should figure out that it’s not for regular display purposes. In any case, I havent had any issues with this.

      Hope this helps!

      Alex

      Like

      Reply

  25. Hi Alex, thanks for this tutorial! Question – do you have a similar guide anywhere on how to create a CSV file. I used ShareASale for some of my affiliate networks and unfortunately this is how they require we upload our data feed. Thanks in advance for your help!

    Like

    Reply

    1. Yes. Take a look here: https://business.czarto.com/2016/07/08/shopify-fix-your-google-analytics-product-performance-reports/

      This is to create a CSV file to upload to Google Analytics, but you should be able to follow the same general pattern for your needs.

      Template also available on GitHub here: https://github.com/Czarto/ShopifyScripts/blob/master/Templates/collection.csv-ga-product-feed.liquid

      Everything basically needs to be on 2 lines of code, otherwise you’ll get line breaks in your output CSV file. A little annoying to work with, but otherwise works quite well.

      Best,
      Alex

      Like

      Reply

  26. Appreciate the detailed tutorial!

    I’m a little confused as to the Google Shopping App.

    Are you using that to just add the google specific metafields to the admin? Or are the products being pushed via the Google Shopping App in conjunction with the XML feed?

    Thanks!

    Like

    Reply

      1. So the shopping app is pushing the first variant for each product and the xml feed is being used to add the missing variants as well as additional data?

        The Collection used for the Shopping App and the Xml feed should be the same?

        It seems if you don’t do that, then the app doesn’t let you edit the fields.

        Thanks!

        Like

  27. Hi Alex,

    So pleased I just found this pos as have this same issue with Variants. However through shopify all the variants are loading, the issue is all the variants of a single product all have the same MPN id as well as the same title and description. It is also random that some searches display the first variant while some the last variant.

    If I understand form above to use my SEO title and descriptions from the product pages, I juts need to use your updated code and this will do automatically?

    Lastly, have you built a feed for Shopify reviews to Google Merchant centre? I contacted Google about this and need to build a feed: https://developers.google.com/product-review-feeds/

    Thanks for your assistance and great post!

    Seán

    Like

    Reply

    1. Hi Sean,

      Yes, use the updated code and set UseSEOTitle = true and UseSEODescription = true at the top of the file and it should “just work”.

      I have not yet built a feed for the product review feed, but I think this will come shortly. (I will post an update here when it does).

      Best,

      Alex

      Like

      Reply

  28. Hi Alex. No worries, and thanks for the update. I’ve just had a look at the feed rules and I can just about get my head around them, which is good. Are you suggesting that I lose the recently added code and revert to the {% assign Gender = product.metafields.google.gender %} and {% assign AgeGroup = product.metafields.google.age_group %} code and just use the feed rules instead? Thanks

    Like

    Reply

    1. I think if it’s working, then leave it as is. But in the future, if you want to add more conditions, try using the feed rules first as I think it’s a cleaner and more maintainable solution in the long term.

      Like

      Reply

      1. Hi Alex. I’m afraid I’m back for a little more advice. I’ve run into an error with my feed. I’m getting a “missing microdata for condition” warning for some of my products. I read that it shouldn’t be an issue, however many of my products are not listing in Google Shopping and someone at Google Merchant Centre told me this could be the cause of the problem. I’ve run the product urls through Google’s Structured Data Testing Tool and the error is listed as “One of price or priceSpecification must be provided” relating to this line of code: . Do you have any suggestions please? Once again, thanks in advance!

        Like

      2. This post explains how to properly add microdata to your product pages so that Google Merchant Center stops complaining: https://business.czarto.com/2016/12/13/adding-schema-org-microdata-to-your-shopify-product-pages-to-enable-google-merchant-center-automatic-updates-with-product-variant-support/

        Some warnings on this are that (1) You will have to get your hands dirty with code; (2) the code you need probably won’t be exactly as in the post as it depends on what theme you are using; and (3) Google Merchant Center can take a few weeks before the errors start to disapear…

        Hope that helps!

        Liked by 1 person

  29. Hi Alex. Thanks for your help. I’ve managed to get the gender tag to work after experimenting with the case and removing the {% assign Gender = product.metafields.google.gender %} form earlier in the code, however I’m struggling with the age_group tag. It just returns Toddler or I get an error message. I’ve tried it with the {% assign AgeGroup = product.metafields.google.age_group %} code, which just returns Toddler regardless of the value and without, which returns a missing age group warning. Any ideas what I’m doing wrong? The Google AgeGroup values you specified are correct by the way.

    Thanks!

    Like

    Reply

    1. Just a quick update, I now realise I need some code similar to this: {% if Size contains ‘1-2’ or ‘3-4’ %}{% assign AgeGroup = ‘toddler’ %}{% else %}{% assign AgeGroup = ‘kids’ %}{% endif %}, but since I know nothing about coding, it’s obviously not right. Would you mind correcting it for me? Thanks in advance.

      Like

      Reply

      1. Hey, I got it! {% if Size contains ‘1-2’ or Size contains ‘3-4’ %}{% assign AgeGroup = ‘toddler’ %}{% else %}{% assign AgeGroup = ‘kids’ %}{% endif %} Can’t believe I’m coding now. Thanks for all your help, you’re a legend!

        Like

      2. 🙂 Happy it worked out!

        After sleeping on this a bit, I realized there is an easier way to handle your color/size customizations using the Google Merchant Feed rules. If you click on your feed in Google Merchant center, there should be a tab called “Feed Rules”.

        Eg: You can create a new rules as follows:
        – Target Attribute: age_group
        – Create value based on criteria in feed: If age_group in_range 1 to 2 set value to Toddler
        – Else: If age_gorup in_range 3-4 set value to infant

        etc… I think this is cleaner than having a bunch of if statements in your template code.

        Sorry for not thinking of it sooner! 🙂

        Like

  30. I’m selling children’s clothing and have T-shirts in both blue and pink (so male and female) and toddler and children sizes, all variants of the same product. I therefore have different values populating the ‘Google Shopping / Age Group’ and ‘Google Shopping / Gender’ fields for each product. Your code currently assigns the main product values to Gender and AgeGroup. Is there any way to assign the variant values rather than the product values please?

    Hope that makes sense.

    Cheers!

    Like

    Reply

    1. You would need code similar to this, right before the tag:


      {% if Color == 'pink' %}{% assign Gender = 'female' %}{% elsif Color == 'blue' %}{% assign Gender = 'male' %}{% endif %}
      {% if Size contains 'toddler' %}{% assign AgeGroup = 'toddler' %}{% elsif Size contains 'kids' %}{% assign AgeGroup = 'kids' %}{% endif %}

      (But double check the required Google AgeGroup values, as the above is just from memory. Also, not sure if case sensitivity will be an issue when check colors)

      Like

      Reply

  31. Hi Alex, i’m sturggling to get the collection to be hidden on the product page… here is the code, can you advise where i need to be putting the unless statement, everything else is working like a dream.

    {% if settings.display_collections %}

    {{ ‘products.product.collections’ | t }}:

    {% for col in product.collections %}
    {{ col.title }}{% unless forloop.last %},{% endunless %}
    {% endfor %}

    {% endif %}

    Like

    Reply

    1. Hi Rich,

      I believe you would put it just inside your for loop like so:

      —–

      {% if settings.display_collections %}

      {{ ‘products.product.collections’ | t }}:

      {% for col in product.collections %}
      {% unless collection.title contains “xml” %}
      {{ col.title }}{% unless forloop.last %},{% endunless %}
      {% endunless %}
      {% endfor %}

      {% endif %}

      —–

      Let me know if that works.

      Like

      Reply

      1. No it’s still showing the collection is called google test and this is what i have in the code….

        {% if settings.display_collections %}

        {{ ‘products.product.collections’ | t }}:

        {% for col in product.collections %}
        {% unless collection.title contains “google” %}
        {{ col.title }}{% unless forloop.last %},{% endunless %}
        {% endunless %}
        {% endfor %}

        {% endif %}

        Many thanks for your help.

        Like

      2. The only thing I can think of, is that I believe “contains” is case sensitive, so if your collection is called “Google Test” then your code needs to be:

        {% unless collection.title contains “Google” %}

        (So “Google” with a capital “G”).

        Like

  32. Creative, simple and an affordable solution Alex to a frustrating problem! This approach is required if you want your shopping campaign to target multiple countries. You can use the currency conversion feature inside merchant center, but Google still requires you to submit unique feeds per country even if the data remains the same.

    I recommend a custom label field be used to designate pricing categories so bidding can be discriminated for low/high priced and ROI products. I haven’t created the liquid for this yet though.

    Liked by 2 people

    Reply

  33. Hey Drew,

    Working on the exact same thing now, too. Make sure you select the modified “collection.xml-product-feed” option from the Templates drop down in the Collection page you created for this. I forgot to (left it as the default “collection”) and got the same error message. Waiting for this to finish fetching, but I think that’s the problem.

    Like

    Reply

  34. Hi Alex,

    I’m following this guide step by step (thanks for publishing it), but i’m running into an error when i’m trying to grab the feed.

    The file URL for me feed is : http://www.home-fashion-designs.myshopify.com/collections/google-shopping-feed-avignon-quilt

    and its returning this error: Feed file is in a format that we don’t support: HTML. Please make sure you upload your feeds in one of our documented formats.

    Any input on this would be greatly appreciated

    Thanks,

    -Drew

    Like

    Reply

  35. Thanks for this! It’s also worth mentioning that you need to associate the XML template with the collection. This is done with the “Theme template” dropdown in the right sidebar when creating/editing a collection.

    Like

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s