XML Format Guide
Feeds must conform to the Google Product Feed XML format. The file is an RSS 2.0 document with product data inside <item> elements under a <channel>. Google-specific fields use the g: namespace prefix (http://base.google.com/ns/1.0).
Basic Structure
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>My Product Catalog</title>
<link>https://www.example.com</link>
<description>Product feed</description>
<item>
<!-- Product fields go here -->
</item>
<item>
<!-- Another product -->
</item>
</channel>
</rss>Each <item> represents a single product variant (SKU). The service parses every item, groups them by item_group_id into offers, and transforms them into standardized Violet platform products.
Supported Fields
All Google-namespaced fields use the g: prefix. The <title> and <description> elements can appear with or without the prefix.
Product Identity
<g:id>
Yes
string
Unique identifier for this product variant (SKU). Each item in the feed must have a distinct ID. This becomes the SKU's external_id in the Violet platform.
<title>
Yes
string
Product title. Used as both the offer name and SKU name. Keep it descriptive but concise (e.g., "Nike Air Max 90 - Black/White - Size 10").
<g:item_group_id>
No
string
Groups multiple items into a single parent product (offer). All items sharing the same item_group_id become SKU variants under one offer. See Grouping Items Under a Parent Product.
Description & Links
<description>
No
string
Detailed product description. Mapped to the offer's description field.
<link>
No
string (URL)
URL to the product page on your website. Mapped to the offer's external_url.
<g:image_link>
No
string (URL)
URL of the main product image. Should be a high-quality image (at least 800x800 pixels recommended).
Pricing
Prices are specified as a decimal value followed by a space and a 3-letter ISO 4217 currency code (e.g., 79.99 USD). European decimal format is also supported (e.g., 79,99 EUR). Prices are converted to integer cents internally (e.g., 79.99 USD becomes 7999).
<g:price>
Yes
string
The current selling price. Format: {amount} {currency} (e.g., "29.99 USD", "1,234.56 CAD"). If no sale_price is provided, this value is used as both the retail price and sale price.
<g:sale_price>
No
string
A discounted price. When present, this becomes the SKU's sale price and the price field becomes the retail (original/MSRP) price. Same format as price.
<g:offer_price>
No
string
An alternative offer price. Parsed but reserved for future use.
Supported currency codes: USD, EUR, GBP, CAD. Currency symbols ($, €, £) are also recognized. If no currency is specified, USD is assumed.
Pricing examples:
Availability & Inventory
<g:availability>
Yes
string
Stock status. Accepted values: in stock, in_stock, out of stock, out_of_stock, preorder. Items with in stock or in_stock are marked as available.
<g:inventory>
No
integer
Exact quantity available. When provided, enables inventory tracking with precise stock counts. Takes priority over <stock> and <g:availability> for quantity.
<stock>
No
string
Custom stock quantity field. Supports formats like "5", "3+", "10+". Used as a fallback when <g:inventory> is not present. Note: this field does not use the g: namespace.
Inventory resolution order: The service determines stock quantity using the first available source:
<g:inventory>— Exact quantity, enables inventory tracking<stock>— Parsed quantity (the+suffix is stripped), enables inventory tracking<g:availability>— Binary in-stock/out-of-stock only, no quantity tracking
Product Identifiers
<g:gtin>
No
string
Global Trade Item Number (UPC, EAN, ISBN, or JAN). Mapped to the SKU's gtin field.
<g:mpn>
No
string
Manufacturer Part Number. Mapped to the SKU's upc field.
<g:brand>
No
string
Product brand or manufacturer name. Mapped to the offer's vendor field.
Condition
<g:condition>
No
string
Product condition. Accepted values: new, refurbished, used. Parsed and stored on the feed item.
Categorization
<g:google_product_category>
No
string
Google product taxonomy category. Takes priority over product_type for categorization. Example: "Apparel & Accessories > Shoes > Athletic Shoes".
<g:product_type>
No
string
Your own product categorization. Used as a fallback when google_product_category is not set. Example: "Men's Footwear > Running Shoes".
Variant Attributes
These fields define how product variants differ from each other. When items are grouped by item_group_id, these attributes become selectable variant options on the offer (e.g., a color picker or size dropdown).
<g:color>
No
string
Product color. Creates a "Color" variant on the offer. Example: "Navy Blue".
<g:size>
No
string
Product size. Creates a "Size" variant on the offer. Example: "10", "Medium", "32W x 30L".
<g:material>
No
string
Primary material. Creates a "Material" variant on the offer. Example: "Leather", "Cotton Blend".
<g:pattern>
No
string
Product pattern or print. Creates a "Pattern" variant on the offer. Example: "Striped", "Plaid".
Demographic Attributes
These fields are stored as offer-level metadata rather than variant attributes.
<g:age_group>
No
string
Target age group. Accepted values: newborn, infant, toddler, kids, adult. Stored as offer metadata with key age_group.
<g:gender>
No
string
Target gender. Accepted values: male, female, unisex. Stored as offer metadata with key gender.
Grouping Items Under a Parent Product
Use <g:item_group_id> to group multiple items (SKUs) into a single offer. This is how you represent a product that comes in multiple sizes, colors, or other variants.
How it works:
All items with the same
item_group_idare grouped into one offerEach item becomes a separate SKU under that offer
Variant attributes (
color,size,material,pattern) on each item become selectable optionsThe first item in the group provides the offer-level details (title, description, link, brand, category)
Pricing is aggregated across all SKUs — the offer tracks the min and max price
Items without an item_group_id are treated as standalone offers with a single SKU. The item's <g:id> is used as the group key.
Example: T-Shirt with Color and Size Variants
This produces one offer (TSHIRT-001) with:
3 SKUs:
TSHIRT-WHT-S,TSHIRT-WHT-M,TSHIRT-BLK-SVariant "Color": White, Black
Variant "Size": S, M
Variant "Material": Cotton
Price range: min = 2499, max = 2499
Handling Images
Each item supports a single <g:image_link> for its main product image. To associate different images with different variants, provide a unique image_link per item.
Note: The
<g:additional_image_link>element from the Google Product Feed specification is not currently supported. Only the primary<g:image_link>is processed per item.
Standalone Products (No Variants)
Products that don't come in multiple variants can omit <g:item_group_id>. Each item becomes its own offer with a single SKU.
This produces one offer with one SKU, both using GADGET-042 as their external ID.
Sale Pricing Example
To show a discounted price alongside the original price, provide both <g:price> (the original/MSRP) and <g:sale_price> (the current discounted price).
Result: retail_price = 19999 (cents), sale_price = 12999 (cents).
When only <g:price> is provided (no <g:sale_price>), the same value is used for both retail_price and sale_price.
Minimal Valid Feed
The smallest valid feed requires at minimum <g:id>, <title>, <g:price>, and <g:availability> on each item:
Complete Feed Example
A full-featured feed with grouped variants, sale pricing, inventory tracking, and all supported fields:
This feed produces:
Offer 1 (
CHARGER-USB-C): Standalone charger, 1 SKU, sale price $29.99 (retail $39.99)Offer 2 (
CASE-PRO): Phone case group, 3 SKUs, variant "Color" (Black, Navy, Clear), variant "Material" (Polycarbonate, TPU), price range $29.99–$34.99
Field-to-Platform Mapping Reference
This table shows how each XML field maps to the Violet platform's Offer and SKU models.
Offer-level fields (set from the first item in a group):
<g:item_group_id> or <g:id>
external_id
Group ID if present, otherwise item ID
<title>
name
<description>
description
<link>
external_url
<g:brand>
vendor
<g:google_product_category>
source_category_name
Priority over product_type
<g:product_type>
source_category_name
Fallback if no Google category
<g:availability>
available
true if "in stock" or "in_stock"
<g:price>
min_price, max_price
Aggregated across all SKUs in the group (in cents)
<g:age_group>
metadata age_group
Stored as offer metadata
<g:gender>
metadata gender
Stored as offer metadata
SKU-level fields (set per item):
<g:id>
external_id
<title>
name
<g:price>
sale_price, retail_price
Converted to cents. Both set to same value unless sale_price is provided
<g:sale_price>
sale_price
Overrides price as sale_price; price then becomes retail_price only
<g:gtin>
gtin
<g:mpn>
upc
Mapped to UPC field
<g:inventory>
qty_available
Enables inventory_tracked = true
<g:availability>
in_stock
Fallback when no inventory or stock field
<g:color>
variant value "Color"
<g:size>
variant value "Size"
<g:material>
variant value "Material"
<g:pattern>
variant value "Pattern"
Unmapped Fields and SKU Metadata
The Google Product Feed specification includes fields beyond those listed above. Any additional Google Product Feed fields that do not have a one-to-one mapping to existing properties on the Violet Offer or SKU models are captured as metadata on each SKU.
For example, fields like <g:shipping_weight>, <g:custom_label_0>, or <g:energy_efficiency_class> do not map directly to a dedicated Offer or SKU property. Instead, they are stored as key-value metadata entries on the SKU, preserving the original field name as the key and the element's text content as the value.
This means you can include any valid Google Product Feed field in your XML and the data will not be lost — it will be accessible through the SKU's metadata collection even if it doesn't appear in the mapping tables above.
Last updated
Was this helpful?

