Skip to content
feedlab Request early access

Feed format

XML (RSS 2.0)

RSS 2.0 feed

An RSS 2.0 product feed wraps each product in an item element inside a channel, with attributes carried as elements in the Google namespace. It is the most widely accepted XML format, and unlike a delimited file it cannot be broken by a comma or a line break in a description.

Specification

File extension
.xml .rss
Content type
application/rss+xml; charset=utf-8
Compression
Gzip is widely accepted and worthwhile, because XML is considerably more verbose than a delimited file.
One product is
A single rss root element containing one channel, which holds the feed title, link and description followed by one item element per product. Each attribute is a child element in the g: namespace, so g:id, g:title, g:price and so on.
Escaping
Reserved characters must be escaped as entities: ampersand, less-than and greater-than at minimum. A value containing markup can be wrapped in CDATA instead, which is the usual approach for descriptions. Declare the Google namespace on the rss element or every namespaced element is ignored.

A valid rss 2.0 feed

Two products, every required attribute, nothing omitted for brevity. Copy it and replace the values.

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <title>Northbound</title>
    <link>https://example.com</link>
    <description>Northbound product feed</description>
    <item>
      <g:id>SHIRT-BLK-M</g:id>
      <g:title>Northbound Oxford Shirt, Black, Medium</g:title>
      <g:description>A long-sleeved Oxford shirt in 100% brushed cotton.</g:description>
      <g:link>https://example.com/products/oxford-shirt?variant=101</g:link>
      <g:image_link>https://cdn.example.com/oxford-black.jpg</g:image_link>
      <g:availability>in_stock</g:availability>
      <g:price>49.00 GBP</g:price>
      <g:brand>Northbound</g:brand>
      <g:gtin>05012345678900</g:gtin>
      <g:condition>new</g:condition>
      <g:item_group_id>SHIRT-OXFORD</g:item_group_id>
    </item>
    <item>
      <g:id>SHIRT-BLK-L</g:id>
      <g:title>Northbound Oxford Shirt, Black, Large</g:title>
      <g:description>A long-sleeved Oxford shirt in 100% brushed cotton.</g:description>
      <g:link>https://example.com/products/oxford-shirt?variant=102</g:link>
      <g:image_link>https://cdn.example.com/oxford-black.jpg</g:image_link>
      <g:availability>out_of_stock</g:availability>
      <g:price>49.00 GBP</g:price>
      <g:brand>Northbound</g:brand>
      <g:gtin>05012345678917</g:gtin>
      <g:condition>new</g:condition>
      <g:item_group_id>SHIRT-OXFORD</g:item_group_id>
    </item>
  </channel>
</rss>

Which channels accept it

Channel support for XML (RSS 2.0)
Channel Support Notes
Google Shopping Supported The most common XML format for a Merchant Center feed.
Meta Supported Accepted for a catalogue data feed.
Microsoft Advertising Supported Accepted alongside tab-delimited text.
Pinterest Supported Accepted for a scheduled data source.
OpenAI Not supported OpenAI takes Parquet, JSONL, CSV or TSV, all gzipped or compressed.

What breaks a rss 2.0 feed

A missing namespace declaration silently empties the feed

Without xmlns:g on the rss element, every g:-prefixed element is invalid. The file still parses as XML and the channel reports items with no attributes rather than a namespace problem, which sends people looking at their mapping instead of their root element.

An unescaped ampersand invalidates the document

Product URLs carry query strings, and an ampersand between parameters must be written as an entity. One raw ampersand makes the whole document unparseable, so the feed fails entirely rather than losing one item. This is the single most common XML feed failure.

HTML in a description needs CDATA, and CDATA needs care

Shopify descriptions are rich text. Wrapping them in CDATA lets the markup through, which is convenient and usually wrong, because most channels want the description stripped of HTML. If you do use CDATA, a literal "]]>" inside the value terminates it early.

Verbosity has a real cost

The same catalogue is several times larger as XML than as TSV, because every value carries an opening and closing tag. On a large catalogue that affects generation time, transfer time and the channel's own fetch timeout, which is why gzip matters more here than elsewhere.

Frequently asked questions

What does the g: prefix mean in a product feed?

It is the Google namespace, declared as xmlns:g="http://base.google.com/ns/1.0" on the root element. It distinguishes product attributes from the RSS elements that surround them, and without the declaration every namespaced element is ignored.

Should I use RSS 2.0 or Atom 1.0 for a product feed?

RSS 2.0 is more common and slightly simpler, with fewer required elements around the products. Both are accepted everywhere XML is, so the choice rarely matters unless something downstream already expects one of them.

Why does my XML feed fail to parse?

Most often an unescaped ampersand in a product URL. XML requires it as an entity, and a single raw one invalidates the entire document rather than a single item.

Do I need CDATA for product descriptions?

Only if the value contains markup, and most channels want the HTML stripped anyway. Escaping the reserved characters is enough for plain text, and it avoids the trap of a literal "]]>" closing the section early.

Errors this format causes

Related concepts

Primary sources

Channel specifications change. These are the official documents this page is based on.

Last reviewed View as markdown