Instructions to get Ubercart products added to Google Merchant Center (Google Shopping). Instructions are obviously outlined for Ubercart, however the bulk of the instructions should work for Drupal Commerce with a few tweaks.
While it's perfectly fine to add the custom shopping fields directly to your product node, I have learned from experience that you are better off leveraging an entity mechanism to house the shopping details outside of the product, then reference that entity on the product. My personal favorite to accomplish this is Paragraphs. I have learned that if I use paragraphs to house the fields for Google Shopping, I can "add" that paragraph to the product page if I need it. If I have a group of products that won't ever be on Google Shopping, I don't have the extra strain on that node caused by having a bunch of fields that are required to load but don't hold any info.
I know for a fact that Paragraphs works fine but I haven't tested ECK or Field Collection. In theory, they should both work just fine though.
Merchant Center XML Feed Setup
- Setup new view "content" of type "product"
- Uncheck "create a page"
- "Unformatted list" of "fields"
- Items to display "0" (For all items)
Merchant Center XML Feed Configuration
Add "Data Export"
Add whatever title makes sense to you
Format: XML file
The settings we'll have to come back to ad check boxes to "Disable encoding of XML entities for these fields" once fields are added, however two major settings can be changed up front.
Root Node: channel
Item Node: item
Most of the view fields sit within a gray area... You can easily use the existing fields for your site, or you can do what I did and create fields for the product that are specific to Google Shopping.
The following is a list of fields I added to the view. Make sure to change the label to the google xml identifier as denoted from the Merchant Center Help Docs
After each field, I'll denote whether it's a Core View Field, a Core UC Field, a Custom View Field, or a Custom Content Type Field. Keep in mind the "Custom Content Type" can be substituted for your own needs, For example, the description you could easily just use the body of your page or summary of the body. The Title, you could use the title of the page. I created my own separate fields specifically targeting the info I present to Google Shopping. Other fields like "Availability" or "Condition" can either be done as a custom field on the product or you can override ALL of them with a custom view field. It's really up to you. (For example, I used a view field for condition and overrode the results because all I sell is "new" items so there's no reason for me to have a list field on the product page.)
Content: Nid (g:id) | Core View Field
Content: Shopping Title (title) | Custom Content Type Field
Content: Path (link) | Core View Field
Content: Shopping Description (g:description) | Custom Content Type Field
Content: Image (g:image_link) | Core UC Field
Content: Availability Options (g:availability) | Custom Content Type Field
Product: Sell price (g:price) | Core UC Field
Global: Custom text (g:google_product_category) | Custom View Field
Content: Product Type (g:product_type) | Custom Content Type Field
Content: Product UPC (g:gtin) | Custom Content Type Field
Content: Product MPN (g:mpn) | Custom Content Type Field
Content: Product Brand (g:brand) | Custom Content Type Field
Content: MPN Available (g:identifier_exists) | Custom Content Type Field
Global: Custom text (g:condition) | Custom View Field (this could easily be a custom content type field)
Content: Shipping Banner (g:shipping_label) | Custom Content Type Field
Product: Weight (g:shipping_weight) | Core UC Field
Content: Path (link) | (edit and check "Use absolute link" under the rewrite results section. This will make sure your domain name is added to the link)
Content: Image | (edit and change "Formatter" to "Image URL" and URL Type is "Full URL". This formatter removes all html code from the output and simply displays the URL)
Product: Sell price | Change the formatter to Numeric and set the thousands separator to none
Global: Custom text (g:google_product_category)| I simply set a single category for my store setup. If you need more categories, you might have to get a bit more creative. google docs.
Content: MPN Available | This was simply a Boolean field with a Yes or No. It tells Google whether an identifier is available or not. Learn about it here
Global: Custom text (g:condition) | If you use a custom field, use that instead. Otherwise if all of your products are "new", you can simply set the text to "new".
Views Filter Criteria
Add the filters that make sense for your situation. I recommend adding filters that will keep the product from showing if a field is empty. Otherwise you run the chance of Google Shopping kicking back a bunch of errors and disapproving products.
View Data Export Settings
Path: call the file whatever suits your needs. (ex. google-shopping.xml)
We need to override two (2) template files to make Google Shopping work. One for the header and one for the footer. Comment out on: https://www.drupal.org/node/2764979 so we wouldn't have to do this.
Create theme template file in your themes "templates" folder called: views-data-export-xml-header.tpl.php. This assumes you only need 1 xml file for your site... Otherwise you will need to use better declarative template file names.
(You might have to double check your theme name within the views "theme information" area, but if you haven't re-named anything, it should work.)
We need to add some RSS version info stuff to the header of the view that looks like
rss version="2.0" xmlns:g="http://base.google.com/ns/1.0"
Add the rss version part right above the $root_node section like the following:
* @file views-view-table.tpl.php
* Template to display a view as a table.
* - $title : The title of this group of rows. May be empty.
* - $rows: An array of row items. Each row is an array of content
* keyed by field ID.
* - $header: an array of headers(labels) for fields.
* - $themed_rows: a array of rows with themed fields.
* @ingroup views_templates
// Short tags act bad below in the html so we print it here.print '<?xml version="1.0" encoding="UTF-8" ?>';
<?php print "\n" ?>
<<?php print 'rss version="2.0" xmlns:g="http://base.google.com/ns/1.0"' ?>>
<<?php print $root_node; ?>>
Next, we need to close the RSS in the footer template file views-data-export-xml-footer.tpl.php.
</<?php print $root_node; ?>>
At this point, you can save the view and review the data. The preview only outputs 25 or so results, so to make sure all of your products are in the feed, you'll have to check the actual feed.
If you have HTML code showing up in the feed, this is where you'll have to go back to the View Format -> Settings and add a checkbox to the various fields under the Disable encoding of XML entities for these fields area.
Create a new content view of type products
The microdata feed is so Google can crawl your website for updates. Google is kind of stupid about this... It will throw a bunch of errors if the microcode isn't available, but yet if you set your feed to automatically upload once a day and Google only crawls your site every three days, it makes their errors rather stupid. I digress...
Format: Unformatted list | Settings
Show: Fields | Settings
Add Content Pane (panels users) or Block (non-panels users)
If you're using panels, you can use a panel pane. Just make sure to set the "Argument Input -> From Panel argument -> First"
If you aren't using panels, just add it as a block.
You don't need many fields to make Google happy with the microdata. I added the following below (see previous section about the fields sent in the xml feed)
Make sure to check off "Exclude" on ALL of the fields EXCEPT the first Global: Custom text. Leave the output of the first Global: Custom text blank. The purpose of this field is to keep views from freaking about "no usable fields".
Global:Custom text (place holder)
Content:Custom text (condition) (see above)
Product: Sell price
Content: Product MPN
Add Views Header
Next, add a views header -> Global: Text area
Make sure "Use replacement tokens from the first row" is checked
Format your microdata code like the following example (using your tokens from the replacement pattern)
<div class="product-microdata" style="display: none;">
<div itemscope itemtype="http://schema.org/Product">
<meta itemprop="name" content="[field_product_promo_title]"/>
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<meta itemprop="price" content="[sell_price]"/>
<meta itemprop="itemCondition" itemtype="http://schema.org/OfferItemCondition" content="[nothing]"/>
<meta itemprop="pricecurrency" content="USD"/>
<meta itemprop="mpn" content="[field_product_mpn]"/>
Make note of "content="[nothing]" in the OfferItemCondition area. This token is for a global text which uses the tokens [nothing], [nothing1] etc. Since everything I sell is new, I simply created a global text field in the view and set the rewrite text to "new".
Once you have the view setup, make sure you add it somewhere to your product pages. If you use a block, have it only show up on the pages that are products.
Finally, check the source code and make sure it's working properly for a given product page. If not, tweak the microdata view until you're satisfied.