← Back to blog
6 min readBy Feedyio

20 Common Product Feed Mistakes - and How to Fix Them

Product feeds are how your catalog reaches Google Shopping, Meta and dozens of marketplaces - and almost all of them are XML. The frustrating part is that a single malformed character or a wrong field value rarely breaks loudly. Instead it gets individual products quietly rejected or your whole feed marked invalid, and you lose sales without an obvious reason. Below are the 20 mistakes we see most often, each with the wrong version, the fix, and a short note on why it matters.

1. Improper XML declaration

The XML declaration must be the very first thing in the file - no blank line, no comment, no byte-order mark (BOM) before it. It should also state the encoding. If anything precedes it, most parsers reject the document outright.

❌ Wrong


<!-- generated by export tool -->
<?xml version="1.0"?>
<products>...</products>

✅ Fixed

<?xml version="1.0" encoding="UTF-8"?>
<products>...</products>

2. Unclosed or mismatched tags

Every element you open has to be closed, and the closing tag has to match the one you opened. A single missing </address> makes the whole feed invalid, so nothing imports - not just that one product.

❌ Wrong

<item>
  <title>Desk Lamp</title>
  <address>
    <city>Prague</city>
</item>

✅ Fixed

<item>
  <title>Desk Lamp</title>
  <address>
    <city>Prague</city>
  </address>
</item>

3. Unescaped reserved characters

The characters &, < and > have special meaning in XML. A raw ampersand in a title or description is the single most common reason a feed fails to parse. Escape it as &amp; or wrap the text in CDATA.

❌ Wrong

<title>Salt & Pepper Mill</title>

✅ Fixed

<title>Salt &amp; Pepper Mill</title>

4. Undeclared namespace

Google Shopping feeds use the g: prefix (g:price, g:availability, …). That prefix only works if you declare its namespace on the root element. Without the declaration the document is not well-formed and every g: field is unrecognised.

❌ Wrong

<rss version="2.0">
  <channel>
    <item><g:price>99.99 USD</g:price></item>
  </channel>
</rss>

✅ Fixed

<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <item><g:price>99.99 USD</g:price></item>
  </channel>
</rss>

5. Nesting / overlapping tags

Elements must nest cleanly: a child opened inside a parent has to close before that parent does. Overlapping tags like <a><b></a></b> are never valid XML, even though they look harmless.

❌ Wrong

<title><b>Sale</title></b>

✅ Fixed

<title><b>Sale</b></title>

6. Multiple root elements

An XML document must have exactly one root element. Two <item> elements sitting at the top level with nothing wrapping them is invalid - wrap them in a single container such as <channel> or <products>.

❌ Wrong

<item><id>1</id></item>
<item><id>2</id></item>

✅ Fixed

<products>
  <item><id>1</id></item>
  <item><id>2</id></item>
</products>

7. Wrong data type in values

Fields that expect a number have to contain a number. A price like invalid or call us can't be parsed, so the item is dropped. Where a currency is required, include it in the value or the dedicated field.

❌ Wrong

<price>invalid</price>

✅ Fixed

<price>99.99 USD</price>

8. Incorrect CDATA

CDATA lets you drop HTML into a field without escaping it, but it must be opened with <![CDATA[ and closed with ]]> - and the sequence ]]> must not appear inside the content. An unclosed CDATA section swallows the rest of the document.

❌ Wrong

<description><![CDATA[Soft <b>cotton</b> t-shirt</description>

✅ Fixed

<description><![CDATA[Soft <b>cotton</b> t-shirt]]></description>

9. Encoding mismatch

The declaration can say UTF-8, but if the file is actually saved as Windows-1250 the accented characters (ř, ž, ä) arrive as mojibake - or the parser fails on the first byte it can't decode. The file must be saved in the same encoding it declares.

❌ Wrong

<?xml version="1.0" encoding="UTF-8"?>
<title>Příborový set</title> <!-- file saved as Windows-1250 -->

✅ Fixed

<?xml version="1.0" encoding="UTF-8"?>
<title>Příborový set</title> <!-- file saved as UTF-8 -->

10. Duplicate product IDs

Each item needs a unique id. When two products (or two variants) share the same id, the channel treats them as one and keeps only the last - so listings silently disappear from your account.

❌ Wrong

<item><id>SHIRT-01</id><title>Blue shirt</title></item>
<item><id>SHIRT-01</id><title>Red shirt</title></item>

✅ Fixed

<item><id>SHIRT-01-BLUE</id><title>Blue shirt</title></item>
<item><id>SHIRT-01-RED</id><title>Red shirt</title></item>

11. Inconsistent or misspelled tag names

XML is case-sensitive, and importers match field names exactly. A typo like <prodcut>, or mixing <price> and <Price>, means the field is simply ignored and any data it carried is lost.

❌ Wrong

<prodcut>
  <Price>19.99 USD</Price>
</prodcut>

✅ Fixed

<product>
  <price>19.99 USD</price>
</product>

12. Raw HTML in fields without CDATA/escaping

The title field is meant to be plain text - raw markup inside it breaks the XML and looks wrong in listings anyway. Keep titles plain, and put formatted HTML only in fields that allow it (like description), wrapped in CDATA.

❌ Wrong

<title>Big <b>Sale</b></title>

✅ Fixed

<title>Big Sale</title>
<description><![CDATA[Big <b>Sale</b> this weekend]]></description>

13. Inconsistent attribute quoting

Attribute values must be quoted, and you shouldn't mix single and double quotes within the document. Inconsistent quoting trips up stricter parsers and makes the feed harder to maintain. Stick to double quotes.

❌ Wrong

<product id='123' name="Lamp"></product>

✅ Fixed

<product id="123" name="Lamp"></product>

14. Missing required fields

Every channel publishes a list of required attributes - typically id, title, price and availability. Omit one and the item is rejected, no matter how good the rest of the data is.

❌ Wrong

<item>
  <title>Running Shoes</title>
</item>

✅ Fixed

<item>
  <g:id>RUN-42</g:id>
  <title>Running Shoes</title>
  <g:price>79.00 USD</g:price>
  <g:availability>in_stock</g:availability>
</item>

15. Invalid enum values

Some fields only accept a fixed set of values defined by the channel. availability is the classic example: yes isn't valid - Google expects in_stock, out_of_stock or preorder. An out-of-spec value gets the item rejected.

❌ Wrong

<g:availability>yes</g:availability>

✅ Fixed

<g:availability>in_stock</g:availability>

16. Non-standard / undefined entities

XML defines only five entities (&amp;, &lt;, &gt;, &quot;, &apos;). Made-up entities like &customEntity; - or HTML-only ones such as &trade; - aren't recognised and break parsing. Use a numeric character reference instead.

❌ Wrong

<title>BrandName&trade; Speaker</title>

✅ Fixed

<title>BrandName&#8482; Speaker</title>

17. Invalid product identifiers (GTIN/EAN)

If you send a GTIN it has to be a real one - 8, 12, 13 or 14 digits with a valid check digit. A short or made-up code is worse than none: it gets flagged. When you don't have a GTIN, supply brand + mpn instead.

❌ Wrong

<g:gtin>12345</g:gtin>

✅ Fixed

<g:gtin>0036000291452</g:gtin>
<!-- or, if no GTIN exists: -->
<g:brand>Acme</g:brand>
<g:mpn>AC-1099</g:mpn>

18. Test data / comments left in the feed

Debug comments and placeholder "test" products have a way of surviving into production. At best they clutter the feed; at worst a "test" item with a 0.01 price gets approved and shown to real shoppers. Ship clean production data only.

❌ Wrong

<!-- TODO: remove before launch -->
<item><id>test-1</id><title>TEST PRODUCT</title></item>

✅ Fixed

<item><id>LAMP-01</id><title>Desk Lamp</title></item>

19. Incorrect number / price formatting

Prices need a machine-readable format: a dot as the decimal separator, no thousands separator, no currency symbol glued to the number. 1.299,00 Kč is fine for humans but unparseable for an importer - it expects 1299.00 CZK.

❌ Wrong

<g:price>1.299,00 Kč</g:price>

✅ Fixed

<g:price>1299.00 CZK</g:price>

20. Ignoring feed validation errors

The most expensive mistake is shipping a feed you already know has warnings. Those warnings are products that won't show. Run the feed through an XML validator and the channel's diagnostics (such as Google Merchant Center), and fix the issues before you publish.

❌ Wrong

<!-- "47 items disapproved" - published anyway -->

✅ Fixed

<!-- validate, fix all errors, then publish: 0 disapproved -->

The pattern across all 20 is the same: validate before you publish. A quick pass through an XML validator and your channel's diagnostics catches almost everything above before it costs you a sale. This is exactly what product feeds from Feedyio handle for you - it generates correctly-formatted, validated feeds with the right required fields for each channel, including a ready-to-use Google Merchant Center feed, and keeps prices and stock in sync hourly. Try Feedyio free on the Shopify App Store.