How To Add Ubercart Products To Google Merchant Shopping

Author:
phil
Created:
Saturday, January 21st, 2017
Last Updated:
Tuesday, March 12th, 2019

Disclaimer: Accessing the information on this page means you agree to the Sites Terms of Service


Under Construction

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. Note for Drupal Commerce, see the very bottom of the page for specific instructions detailing some of the tweaks.

Recommended Modules

Paragraphs
or
Field Collection
or
Entity Construction Kit

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.

View Feed

Merchant Center XML View Setup

1) Setup new view "content" of type "product"
2) Uncheck "create a page"
3) Set to "Unformatted list" of "fields"
4) Items to display "0" (For all items)
5) Save & Edit

Merchant Center XML Feed Configuration

View Type:: Add "Data Export"
View Title: Add whatever title makes sense to you (Google Shopping)

Format

Format: XML file
Settings: 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.

Inside the Format area

Root Node: channel
Item Node: item

Fields

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.)

Items marked in red are required by Google to make the feed pass inspection (might be subject to change without notice). google_product_category is required for certain categories... take a look at the Google Merchant docs on google_product_category for details.

Items marked in blue have a unique requirement, where two of the three must be present to pass.

Required Google IDs

Required
g:id
title
link
g:description
g:image_link
g:availability
g:price
g:google_product_category

Requires Two of Three
g:gtin
g:mpn
g:brand

Examples of Fields and ID Labels

Add the fields that you want to use, and replace the "Label" with the Google Merchant identifier. For example, Content: Nid would need the label changed to g:id

If you used paragraphs, don't forget to create a relationship to the paragraph reference field on the product.

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
Global: Custom text (g:condition) | Custom View Field (this could easily be a 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: Product Type (g:product_type) | Custom Content Type Field
Content: MPN Available (g:identifier_exists) | Custom Content Type Field
Content: Shipping Banner (g:shipping_label) | Custom Content Type Field
Product: Weight (g:shipping_weight) | Core UC Field

View Field Notes

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)
Originally, 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. Later, I came back and created a new taxonomy vocab with the list of categories that made sense for my business. I created a text field on the vocab that allowed me to enter the category number with the name, then exposed the terms custom number field to the view.

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 with the three options new, refurbished or used, use that instead. Otherwise if all of your products are "new", you can simply set the text to "new" and forget about it.

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.

- If you used paragraphs to house the Merchant fields, then you can setup a filter to check for whether or not the paragraph was even created.

- I created a custom field called "Enable on Shopping" as a boolean value, that way I could "disable" the info from getting into the feed without having to remove the entire paragraph.

Data Export Settings

Path: call the file whatever suits your needs. (ex. google-shopping.xml)

View Template File
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.

Other

Theme
Create two theme template files in your themes "templates" folder called:

views-data-export-xml-header.tpl.php
views-data-export-xml-footer.tpl.php

These file names assume you only need 1 xml file for your site... Otherwise you will need to use the more specific 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.)

Edit Theme Header Template File

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:

<?php
/**
 * @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 "\n" ?>
<?php print '<' . $root_node . '>'; ?>
<?php print "\n" ?>

Edit Theme Footer Tempalte File

Next, we need to close the RSS in the footer template file views-data-export-xml-footer.tpl.php.

Copy and paste the following into the theme file.

<?php print '</' . $root_node . '>'; ?>
<?php print "\n" ?>
<?php print '</rss>' ?>


At this point, you can save the view and review the data. The views 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.

Microdata

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.

Views Fields
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:Shopping Title
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]"/> </div> </div> </div>

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.

Drupal Commerce

Price Formatter - Remove Currency Symbol

In order to get Drupal Commerce to output the proper price because Drupal Commerce Price formatters suck, you have to 1) create a views template for the price field and 2) stick in a special substr command or whatever to "remove" the stupid currency symbol. Stuff like this should not be this difficult to accomplish.

1) Look at the view theme info and find the price field. I recommend using the view name as the file name, so something like:

views-view-field--google-shopping--commerce-price.tpl.php

2) paste the following into the views template file:

/**
 * @file
 * This template is used to print a single field in a view.
 *
 * It is not actually used in default Views, as this is registered as a theme
 * function which has better performance. For single overrides, the template is
 * perfectly okay.
 *
 * Variables available:
 * - $view: The view object
 * - $field: The field handler object that can process the input
 * - $row: The raw SQL result that can be used
 * - $output: The processed output that will normally be used.
 *
 * When fetching output from the $row, this construct should be used:
 * $data = $row->{$field->field_alias}
 *
 * The above will guarantee that you'll always get the correct data,
 * regardless of any changes in the aliasing that might happen if
 * the view is modified.
 */
?>
<?php   echo substr($output, 1 ); ?>

3) Clear caches and it should be good.

Post Comment

(If you're a human, don't change the following field)
Your first name.
(If you're a human, don't change the following field)
Your first name.