Generate WooCommerce Product Feed for Google

WooCommerce based store owners can easily take advantage of Google Merchant Center to promote their merchandise through Google Shopping and increase sales. In my case one of my client reported this tool to be a great one and they were able to increase their online sales by couple of fold.

Google Merchant CenterGoogle Merchant Center.

Store owners can easily submit their product feed in many different ways. There are both online and offline method. However, I personally prefer to submit an XML based product feed from the root directory of the store URL. In other words the URL for the product feed should look like this:

https://www.yourstore.com/products.xml

Such product feed has many additional benefit over offline method. Perhaps the biggest benefit is to be able to generate the updated product list automatically as go on adding or deleting products. Since Google would check the XML file every day(on an specified time), you wouldn’t have to worry about anything. Google will automatically crawl the data for new items and promote them. Today on this post, I will share a simple snippet that would allow store owners to automatically generate the product feed and update them accordingly.

Let’s take a look at the basic Structure of the RSS 2.0 XML File with a single Product Data.

<?xml version="1.0"?>
<rss version="2.0" xmlns:g="https://base.google.com/ns/1.0">
   <channel>
      <title>The name of your data feed</title>
      <link>https://www.example.com</link>
      <description>A description of your content</description>
      <item>
         <title>Product Title</title>
         <link>https://www.example.com/product-page-url/</link>
         <description>Describe your product here.</description>
         <g:image_link>https://www.example.com/image.jpg</g:image_link>
         <g:price>25</g:price>
         <g:condition>new</g:condition>
         <g:id>1a</g:id>
      </item>
   </channel>
</rss>

I would highly recommend you to read the Google Documentation on RSS 2.0 specification for XML format to learn more. You should also read about the Product Data Specification to better understand that possible attributes that you may or should additionally add on your data feed. This is bit complicated as the requirements changes based on the industry or the type of merchandise you are selling. So, I would leave it up to you to figure that out.

Let’s take a look at our magic snippet.

add_action("save_post","google_merchant_products_feed");
function google_merchant_products_feed() {
   // query products
   $allposts = get_posts(array(
      'numberposts' => -1,
      'orderby' => 'post_date',
      'post_type' => array('product'),
      'order' => 'DESC'));
   // generate xml content
   $gmc = '<?xml version="1.0" encoding="UTF-8"?>';
   $gmc .= '<rss version="2.0" xmlns:g="https://base.google.com/ns/1.0">';
   $gmc .= '<channel>';
   $gmc .= '<title>'.get_option('blogname').'</title>';
   $gmc .= '<link>'.get_option('siteurl').'</link>';
   $gmc .= '<description>'.get_option('blogdescription').'</description>';
   foreach($allposts as $post){
      // get thumb url
      $thumb = wp_get_attachment_url(get_post_thumbnail_id($post->ID));
      // sanitize product short description
      $desc_r = strip_tags($post->post_excerpt); 
      $desc_t = htmlspecialchars(trim($desc_r)); 
      $desc_p = preg_replace("/\r|\n/", "", $desc_t); 
      $desc = strip_tags($desc_p,'<p><a>');
      setup_postdata($post);
      $gmc .= '<item><g:title>'.get_the_title($post->ID).'</g:title>';
      $gmc .= '<g:link>'.get_permalink($post->ID).'</g:link>';
      $gmc .= '<g:description>'.$desc.'</g:description>';
      $gmc .= '<g:image_link>'.$thumb.'</g:image_link>';
      $gmc .= '<g:price>'.get_post_meta($post->ID,'_price',true).'</g:price>';
      $gmc .= '<g:condition>new</g:condition>';
      $gmc .= '<g:id>'.get_post_meta($post->ID,'_sku',true).'</g:id>';
      $gmc .= '</item>'; 
   }
   $gmc .= '</channel>';
   $gmc .= '</rss>';
   $feed = fopen(ABSPATH.'products.xml','w');
   // write the file
   fwrite($feed, $gmc);
   // close the file
   fclose($feed);
}

This is it! Simply copy this snippet on your current theme’s functions.php page and update it. From now on, as soon as you create or update any Product from WooCommerce, this snippet will write (may require permission) an XML file at very root directory of your WordPress site and list every single product that you have.

Additional Note

Now, please keep in mind that this snippet will create a very basic product feed from your site. Content within this file can get really complex depending on the “Product Type” (simple, variable etc.) you are creating from WooCommerce. For an example, if you are running a retail store that sales various products from different Brands, you may need to provide additional data (Brand Name, GTIN etc.) to Google Merchant Center before you run any advertising campaign. I wrote a post explaining how you can add product brand for your WooCommerce products, you may find that post useful and may want to incorporate the data within the XML file. Also take a look at this post to incorporate GTIN on your product feed.

Additional supported attributes can also be added within this snippet to make your life bit easier. However, I highly recommend you submit the basic feed to the Google Merchant Center first and then go about upgrading this snippet based on what Google Merchant Center requires you to fix errors.

Disadvantages

This is something you should read it very carefully and try to understand before you come to your own solution based on my discussion. On this snippet, I have hooked the RSS Feed generation function with the following hook.

add_action("save_post","google_merchant_products_feed");

This basically means, the XML generating function will be fired when you are saving any product or even updating any product. This is both problematic and helpful. It’s sort of problematic if you are running a site with thousands of products and being added/updated on daily basis. It will definitely slow down your product editing or updating process and you will notice it (I did). So basically if you are pressing that blue colored “Publish” or “Update” button hundreds of times in a day, your XML Feed will be generated that many times. This whole process may slow down your entire site as well. However, if you have very few (10-50 estimated) products on your site or you do not need to update them or their inventory on daily basis you have nothing to worry about. This snippet is helpful because you would have the up to date XML Feed as soon as you update or add any product.

Best Practice

From my personal experience I have found this snippet to be more useful if you hook it up with an schedule event method of WordPress. What it means is, you can schedule to update your XML Feed generating process on a specific interval (i.e. hourly, daily etc.). So, basically instead of generating your XML Feed all the time, you can update it once in a day. I already discussed on this issue on one of my previous post. Following this method will help you big way, specially if you run a large site with thousands of products and variations.

Hope that helps. Thank you.

Today In History

  •  
  •  

Comment

15 Comments

    DimitriosPublished: 2 years ago

    I used your great info for making a product feed of my shop. Unfortunately my client doesn’t have SKU and he does not want to add any SKU code. So i would like Google to take the post id instead of the SKU. Thats why i need your help. I found what to change but i don’t know what to right in the snippet. Thank you.

      Iftekhar BhuiyanPublished: 2 years ago

      Dimitrios, thank you for your question. Simply use the following line right before the </item> tag in order to use post ID as your SKU.

       $gmc .= '<g:id>'.$post->ID.'</g:id>';

      Just to be on safe side though, I would highly recommend you to use a “prefix” to give your SKU a professional look. You can use it like this.

      <g:id>MC-'.$post->ID.'</g:id>

      Here, I used “MC” as my prefix. You can replace it with your own desired character. Abbreviated form of your company or business name could be a great way to get your own SKU. I hope you would find this comment to be useful. Thank you once again for stopping by 🙂

    DavePublished: 2 years ago

    Thank you so much! There’s not even a plugin made for this. It worked perfectly 🙂

      Iftekhar BhuiyanPublished: 2 years ago

      Dave, you are welcome. I am happy to know that you found this snippet useful. Cheers.

    LaurPublished: 2 years ago

    It can be added as a plugin ? Thanks!

      Iftekhar BhuiyanPublished: 2 years ago

      Hi Laur, the answer to your question is “NO”. However it can definitely be “made” as a plugin though. Thanks.

    ŁukaszPublished: 2 years ago

    Thank You for article,
    I am having trouble – products.xml file is not saving. The gtin field is filled and updated
    I added all sniplets and trying to change permissions any sugesstion?

      Iftekhar BhuiyanPublished: 2 years ago

      Hello Lukasz, I think it’s more of a “file permission” issue than the snippet. I would highly recommend you to set the file (XML file) permission to “604” (mine is) from FTP and then update one of your product, you may just get lucky 🙂 If everything fails, you can always get in touch with web hosting provider for technical helps.

    StavrosPublished: 2 years ago

    Hello! Thanks for the advice on how to do this! I added the code to my functions.php file, but it doesn’t output any products.xml file on my site, it just goes to a page not found error?

      Iftekhar BhuiyanPublished: 2 years ago

      The only logical reason why you can’t find (seeing error page) the XML file is because it’s not there to begin with. In other words that file has never been created even though you added the snippet. The most common reason is that the folder (root directory) doesn’t have the file writing permission. Here is the solution of your problem.

      1. Create a dummy XML file (*.xml extension is required) on your computer.
      2. Upload the file on your domain’s root directory (using FTP client).
      3. Select the file from FTP and change the file permission numerical value to “604”.
      4. Login to your WP and create a product and publish it (you can delete it later).

      As you publish the new product, our snippet will try to create the XML file. Since we already have (uploaded) an XML file with proper permission, the snippet should be able to update it with all the published products. I hope this resolves your issue. Thank you.

    Michael BayPublished: 2 months ago

    Hi there, Nice snippet, hope you can help me about this:

    [09-Sep-2019 21:43:31 UTC] PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘google_merchant_products_feed’ not found or invalid function name in /home/public_html/new/wp-includes/class-wp-hook.php on line 288

    The snippet dosn’t work with the current WP and WC. I’m running Litespeed, with PHP 7.3. Do you have any ideas?

      Iftekhar BhuiyanPublished: 2 months ago

      Hello Michael,

      Thank you very much for reaching out. Looking at your error log, I realized that I mistakenly missed out the portion (_feed) from the function name. That’s why this function could not fire when you are trying to save or update your products. This happened recently when I updated the snippet to format it properly.

      I made the necessary adjustments on my snippet and tested it with the latest version of WP on my computer, it’s fully functional now. Please try out the updated snippet and please let me know if that solves your issues. Thank you for reporting the error.

    Michael BayPublished: 2 months ago

    Thanks for the quick reply back to me! 🙂 And thanks for the update of the code. It works now 😉 But I have a question or 2 actually.
    $gmc .= ”.wp_trim_words($desc, 40, ‘…’).”;
    This code is only showing 40 words, and in the short description. How can I get more words, and take the full product description instead?

    Is there an option for creating multiple product feed, in the same code? I want to try if I can manage to make a feed to pricerunner, where the field data is a bit different. I was thinking if there was a way in the code, or if I just should duplicate the code, and adjust? So I have this code 2 times in functions, to 2 different XML feed.

      Iftekhar BhuiyanPublished: 2 months ago

      I made number of changes to the snippet upon receiving your questions. If you compare the updated snippet with your current snippet you will find the differences. Now coming to your requests.

      On this updated snippet, I removed the regular product description and added support for “”Product short description”” as you wanted. The word limit has also been removed.

      Yes, you can duplicate the code and make some additional changes to generate two different XML file. However, there are two issue that you need to take in serious consideration.

      1 – Change the name of the function (google_merchant_products_feed) on line one and two to something else. So that you don’t declare the same function twice which would cause fatal error.

      2 – Also change the name of the XML file (products.xml on sixth line from bottom) to something else. Otherwise you will end up overwriting the same file with two different function.

      Now, as I mentioned on my post try to avoid hooking up too many functions and too big product feed with “”save_post”” action. It may dramatically reduce the overall content editing performance. Hope that helps.

    Michael BayPublished: 2 months ago

    Nice nice nice!

    I can easily see the difference, and thanks for the update! Maybe you should still have the code for trimming words, and if someone like to use the small description?

    Actually I am thinking of having both the short description and the product description in the same field. I will try to play with this I think. It could be nice in our shop, because we show these 2 description in 1 field merged together.

    Thanks for the answer about duplicating the code. I will remember these 2 things. Thanks 🙂

    About the “”save_post”” in our Webshop we only have 20 products, and it’s not that often we update our products. But I will look at the schedule options for a time. That could be nice to have this automatic each week or so.

Leave a Reply to Stavros

Note: Convet HTML, PHP, JavaScripts from Postable, before posting from comment section.
License: By submitting a comment here you grant this site a perpetual license to reproduce your words and name/Web site in attribution. Please use your real name or a pseudonym (i.e., pen name, alias, nom de plume) when commenting. If you add your site name, company name, or something completely random, I'll likely change it to whatever I want.