Stefan Holm Olsen

On exporting product catalogs to Google or Facebook

Digital marketers of today might want to work with dynamic product ads, tapping in on the big data that Google and Facebook collects. Instead of manually creating ads, which might be irrelevant when shown, they could set up a template and let the platforms select relevant products and fill in the details.

Enabling product ads require machine readable product data. To showcase how to make that data available, I created a tool for EPiServer Commerce, which generates and provides such a product catalog file.

Why the need?

For what purposes would you need a catalog feed like this?

At some point the digital marketers for your webshop might want to advertise someof the products from the product catalog, and they might want to use Google AdWords or Facebook Ads. No problem there, except that it can be a very manual process of maintaining ads for specific products (instead they might advertise a category or brand).

But to go the whole mile, they could do dynamic product ads, which is another story. They would then be working with Google Merchant Center or Facebook Dynamic Ads (which also covers Instagram).

I personally think that it is a really cool feature, being able to create an ad template (or several; maybe one per product category) and then have the platform fill in the details based on the end user’s actions and interests. Here is a great explanation.

Now, all of this magic requires a product catalog feed and some tracking (that is, if the marketers also want to do re-marketing).

Product catalog feed

Before being able to set up dynamic ads for a product catalog, Google or Facebook need to know about the product catalog. Both platforms support manual upload of catalog files, as well as periodically pulling a dynamically generated catalog feed file.

It is fortunate for us that both Google and Facebook support the same catalog feed format, being the Google Merchant Center format. This can be either a RSS or an Atom feed, containing all the webshop’s products and variants. There should be names, texts, image links, price, shipping price, availability and various products specifications.

When that feed is loaded the digital marketers can go crazy in Google AdWords and Facebook Ads, doing what they do best.


This is beyond the scope of this post. But in short, you might want tracking on the webshop pages. It could be a Google AdWords re-marketing script or a Facebook tracking pixel. Both need different values depending on the product and the specific page (e.g. listing page, detail page, receipt page etc.).

What the tracking scripts do is telling Google and Facebook which products a visitor has seen and what he/she did after looking at these products. Then when the visitor is browsing a page or platform on which there are ads, the systems will try to show offers similar or complementary to what the visitor has seen on the webshop.

You can do without tracking, but without it the dynamic ads would just not be as full featured and precise. If you do go for tracking, remember that the scripts should be generated and rendered dynamically.


I had already done PIM (Product Information Management) projects based on InRiver Product Marketing Cloud. When InRiver exports updated product data it does so through integrations to other systems (e.g. a digital commerce platform). From implementing such integrations, I have learned how to load, transform and export huge sets of product data. So, when I began thinking about how to generate a product catalog feed out of catalogs from EPiServer Commerce, I immediately thought of it like it was an outbound InRiver connector.

After realizing that, I looked up Google’s specification of the catalog file, describing all the fields they support. I really prefer strongly typed classes, so I created classes reflecting these fields and applied proper XML serialization attributes to the properties.

Because I wanted a solution that is independent of any specific catalog model classes, I decided to implement a field mapping concept. To configure which EPiServer meta field corresponds to which field in the catalog file, I therefore created an XML document, including a schema and strongly typed classes. Some fields (e.g. price and inventory) cannot be mapped, though.

Such a mapping file can look like this:

Next up are the services I created for batch loading relevant data, generating feed entry objects and performing streaming serialization. All of this is executed from a scheduled job.

The configuring of the field mapping, feed expiration, selected markets and catalog roots are done in an EPiServer configuration plugin and stored in Dynamic Data Store.

Whenever an XML file is generated it is stored as an EPiServer BLOB, and a reference is stored in Dynamic Data Store. Then, whenever Google or Facebook comes by and requests a catalog file, a WebAPI controller looks it up in the Dynamic Data Store, locates the feed file BLOB and streams out the catalog file.

To sum up, these are the components of my solution:

  • Mapping file: XML document about mapping meta fields to fields in the feed.
  • Services: loading catalog data and transforming it into feed entries.
  • Scheduled job: executing the catalog feed generator.
  • Configuration plugin: presenting and saving the generator configuration.
  • Dynamic Data Store: storing the generator configuration (including the mapping file).
  • BLOB storage: storing the actual catalog feed files (until they expire).
  • WebAPI controller: returning catalog feeds on request.

The source code for this project is available in my GitHub repository. Also available are a binary file and a package, should you not want to build the code yourself.