Shopify Facebook Dynamic Product Ads: Build your own Retargeting feed

If you want to setup Facebook Dynamic Product Retargeting ads for your Shopify store, you need to upload your store’s product catalog feed to Facebook. Below is a walk through of how to generate your Facebook product feed.

This is an advanced topic and I assume you have a basic understanding of HTML/Liquid, the Shopify Store Admin and Facebook Business Manager.

  • UPDATE September 14, 2017: Removed redundant top level products that would cause duplicate products in cases where only a single variant was present.
  • UPDATE September 13, 2017: Fixed issue where some variant images were showing up blank.

Step 1
Install Shopify’s Google Shopping App

Install Shopify’s free Google Shopping app to configure various properties on your products such as Age Group, Gender, and Product Category.

Step 2
Create a Collection Template for your Feed

Create a new custom collection template that will output your collection as XML instead of HTML.

In your Shopify admin, go to:

  • Online Store > Themes > Action > Edit Code
  • Under Templates, choose Add a new Template
  • Choose collection from the drop down and name your template fb-product-feed

Paste the following code into your new template and click Save. (The most recent version of the code is always available on Github here: Shopify Facebook Product Feed Template)

{% layout none %}<?xml version="1.0"?>
<rss xmlns:g="" version="2.0">
{% paginate collection.products by 1000 %}
{% assign CountryCode = 'US' %}
{% if shop.currency == 'CAD' %}{% assign CountryCode = 'CA' %}{% endif %}
{% assign Color = "" %}
{% assign Size = "" %}
<title>{{ }} {{ collection.title | replace: '&', '&amp;' }}</title>
		<link>{{ shop.url }}</link>
<description>{{ collection.description | strip_html }}</description>
{% for product in collection.products %}
  {% assign GoogleProductCategory = %}
  {% assign Gender = %}
  {% assign AgeGroup = %}

  {% if product.variants.size > 0 %}
  {% for variant in product.variants %}
    {% 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 %}
<title>{{ product.title | strip_html | strip_newlines | replace: '&', '&amp;' }}  {{ Color | replace: '&', '&amp;' }}</title>
		<link>{{ shop.url }}{{ variant.url }}</link>
<description>{{ product.title | strip_html | strip_newlines | replace: '&', '&amp;' }} {{ variant.title | strip_html | strip_newlines | replace: '&', '&amp;' }} {{ product.description | replace: '</', ' </' | strip_html | strip_newlines | replace: '&', '&amp;' }}</description>
<g:google_product_category>{{ GoogleProductCategory | replace: '&', '&amp;'  }}</g:google_product_category>
<g:item_group_id>{{ }}</g:item_group_id>
<g:id>{{ }}</g:id>
<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>

  {% endfor %}
  {% else %}
<title>{{ product.title | strip_html | strip_newlines | replace: '&', '&amp;' }}</title>
		<link>{{ shop.url }}{{ product.url }}</link>
<description>{{ product.title | strip_html | strip_newlines | replace: '&', '&amp;' }} {{ product.description | replace: '</', ' </' | strip_html | strip_newlines | replace: '&', '&amp;' }}</description>
<g:google_product_category>{{ GoogleProductCategory | replace: '&', '&amp;'  }}</g:google_product_category>
<g:item_group_id>{{ }}</g:item_group_id>
<g:id>{{ }}</g:id>
<g:price>{{ product.price | money_without_currency }} {{ shop.currency }}</g:price>
<g:availability>{% if product.available %}in stock{% else %}out of stock{% endif %}</g:availability>
<g:image_link>http:{{ product.featured_image.src | product_img_url: 'grande' }}</g:image_link>
<g:gtin>{{ product.barcode }}</g:gtin>
<g:brand>{{ product.vendor }}</g:brand>
<g:mpn>{{ product.sku }}</g:mpn>
<g:product_type>{{ product.type }}</g:product_type>
<g:age_group>{{ AgeGroup }}</g:age_group>
<g:gender>{{ Gender }}</g:gender>
  {% endif %}
{% endfor %}
{% endpaginate %}

or Download from Github:  Shopify Facebook Product Feed Template

Step 3
Assign products to your Feed Collection.

You now need to assign products to your new facebook feed template:

  • Go to Products > Collections
  • Click Create Collection
  • Enter a Title for your feed collection. I recommend Facebook Product Feed.
  • Add the products you want to be included in your Facebook feed, either manually or using conditions.
  • IMPORTANT! Assign your feed TEMPLATE to this collection. In the right column, at the bottom, under Theme Templates, choose : collection.fb-product-feed (the name may change depending on what you actually called your template file).
  • Click Save Colleciton.
  • Preview the collection to make sure it works. You should see unformatted text on the screen. Do a “view source” in your browser to see the formatted XML.
  • Copy the url of this collection as you need it in the next step.

Step 4
Upload your Product Feed to Facebook

  • Log into Facebook Business Manager
  • Go to Assets > Product Catalogs > Product Feeds and click +Add Product Feed to create a new feed.
  • Enter a descriptive name for your feed. (eg: Shopify Facebook Feed); your store’s currency; select recurring or single upload; and click next.
  • Enter your feed collection url you copied in step 3 above. Leave the username & password blank. Choose a time for your daily upload to occur (early morning is usually a good time)
  • Click Create Feed and wait for the feed to be fetched and processed.
  • Fix errors: If there are errors, go back, fix them, re-fetch, and keep doing so until the feed is error free.

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

Step 5
Exclude your Facebook Feed Collection from Showing on your Public Store Pages

Depending on how your store is setup, you may need to add some code to prevent your Facebook feed collection from showing up on your store. The exact way to do this may depend on your theme, but generally you will want to have an “unless” statement within the loop that displays your collections:

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


You are now ready to setup your Dynamic Product Remarketing campaigns!

Related Posts


  1. Trying to get this solution to work, but it seems I’m getting an immediate error when fetching:

    “Parse Error
    Unable to parse on line 3 column 1”

    Went to the feed’s source and there’s just a blank line at line 3…



    1. Hi Wil,

      Unfortunately I haven’t had my hands dirty in the facebook feeds in many months. But planning on getting back into it shortly. I will hopefully have an answer then (and maybe an updated feed).





  2. Hey Alex – as I mentioned in your other post. Instead of relying on the Google Shopping Feed app, can we use this in conjunction with the custom script you made for Google Merchant?



    1. Hi Tanner,

      Although this script (and the Google Merchant Script) will run without the Shopify Google Shopping App, it relies on the app to properly set the Google Shopping Category, as well as Age and Gender properties. So if you don’t want to use the app, you will need to modify the script to assign these values in some other way (either hard-coded, or using an “if” statement)

      Hope this helps?




      1. Alex this helps a ton.

        I was reading through forums on people experiencing an issue involving variants and you mentioned here:

        That if you land directly on the variant page, the Facebook Pixel Helper should show the variant ID, but for me it is not the case.

        Shopify’s new Facebook Pixel integration should automatically be adding the variant shouldn’t it?


      2. Hi Tanner,

        I’ve had issues with the default Shopify integration as well (I believe the implementation has changed several times over the past year). Currently I see the same behaviour — only the top product id is being passed to Facebook.

        The work-around would be to add some custom event code to your product page to trigger an additional “viewcontent” event. I’ll try to implement this and post it as I have time (hopefully in the next couple of months).




      3. Hi Tanner,

        I left a reply on the original shopify thread here: but I’ll duplicate it here again:

        You are correct — currently Shopify only fires the pixel with the product_group / and NOT with the product /

        What you **could** do is fire another facebook event on your product page that sends the VariantId (like here: )

        HOWEVER, I’m not sure if this is a good idea, as you will now have double the product views, and double the add to cart events, etc… Which may lead to double attribution, and double the conversion value being sent to your Facebook business manager:

        But, on the positive side, your dynamic product remarketing should show the correct image / product variant, which should lead to better performance.

        It will all come down to if Facebook is smart enough to figure out that the product_group + product are actually the same thing and dedublicate it.

        Long term, I think that you either have to wait for Shopify to update their implementation, or to NOT use the default Shopify implementation and make your own custom implementation…


  3. Hi Alex,

    Thanks for putting this together!

    Everything has been working great for me so far, except I seem to be getting two listings for each product (one with an image and one without). I’m guessing, this has something to do with the variants, but I was wondering what might be the best way to fix this?




  4. Hi, your tutorial is great and everything is working smoothly, except the product images. If I look in the feed, the image URLs is correct, and shows the products, but when I import to Business manager, all products successfully gets imported, but all of them has no image. Do you have a solution for this?

    Here is an example:

    Best regards



    1. Hi Niklas,

      The latest script code should resolve the missing image issue. Give it a try and let me know how it works out (you may need to delete your existing products/feed and create a new feed).




  5. Hi Alex,

    Thanks for getting back to me. I really appreciate it. This stuff is definitely testing my technical know how! I had been looking at various product feed management services as a solution the downside being that they are all quite expensive and could possibly be overkill?

    Following on from your reply I also had a look and found a variety of apps (both free and paid) in the Shopify app store that seems to offer pretty powerful options when it comes to adding metafields. For instance…

    So with the metafields option am I correct in thinking that I could create additional metafields in order to create an alternate title and alternate product description and somehow configure it so that those fields did not display on my actual Shopify store but were used by the product feed instead of the standard title and product feed. I am not sure that the standard Google Shopping Shopify app that most stores use allows for this type of functionality?

    Would really appreciate your advice on this one.



    1. Hi Scott,

      A tool I would recommend trying first is the ShopifyFD Chrome Plugin:

      By default, MetaFields DO NOT show up on your store unless you explicitly want them to. So you would create 2 new metafields (You need to specify a “namespace” for them — like a top level category — I recommend you use the “google” namespace to keep things consistent with how the Google Shopping app work). Assuming you call the metafields google.title and google.description, you would just update the script code to use and (instead of product.title and product.description).

      A bigger question for you to ask yourself: Is the extra effort and overhead worth the extra sales you are expecting to generate? Going this route means you will theoretically have to manage 3 sets of Titles and Descriptions (The public description, the SEO description, and then your custom Shopping descriptions). I’m not sure what your assumptions are about increased sales due to these optimizations, but I would crunch some numbers first to see if your sales volume supports the overhead of optimizing the descriptions. (Eg: Assume a 10% increase in sales — what does that come to over the period of a year).

      Additionally, in my experience, product description does very little to influence Google Shopping sales (Titles **DO** have a big influence, but not descriptions): — and so I would consider just using the SEO description for this. (..and focus heavily on negative keywords in your PLA campaigns).

      Hope some of this helps!



    2. Hi Scott,

      I just realized that we are talking about the Facebook shopping feed and not the Google shopping feed. My previous comment was related to Google Shopping and not facebook (although all the metafields comments are still correct).

      RE: Facebook – I assume you want to display the description in the product ads, and so need to make it shorter, etc… That makes sense. But I would again make the calculation of how much conversion lift you are expecting from a slightly better description, and if that’s worth the additional short & long term administrative overhead.



  6. Hi Alex, I am wanting the product descriptions for my products on Google Shopping and my Facebook Feed to be different from those on my Shopify store (basically optimised for these channels). Most of the apps I have come across ( the free Google Shopping Shopify app for instance) just pull the product descriptions directly from your Shopify store and don’t give you the option to edit/change them. Can you recommend a solution that would allow me to edit the product descriptions so they differ from those on my Shopify store?



    1. Hi Scott,

      One option is to use the Shopify SEO Title and SEO Description for your feed’s description. But if you’re already using this for your actual SEO description, then that’s not an option.

      The other option would be to use a custom Shopify MetaField to store a third description for each product. There are various metafield editor apps available, as well as a Chrome extension that will allow you to edit them easily. That’s probably your best bet.

      Hope that helps.



  7. Holy ****ing ****!!! You finally got this to work for me! I’ve been trying to get a shopify collection feed to spit out a product feed readable by Facebook for about 3 weeks. Your solution has lead me to believe that we may have stripped essential code from our standard collection template file. The one caveat I’ve found is that you have to make the collection visible on online store in order for it the link to be readable by Facebook’s Product Feed input. This means people could hit that collection page and see a giant block of text. Maybe we can find a work around but again, THANK YOU kind sir. You are a saint.



Leave a Reply

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

You are commenting using your 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