# Product catalog sync

Your product catalog powers personalization across User.com—abandoned cart emails display the exact products users left behind, recommendations surface relevant items, and automations trigger based on product attributes like price drops or stock changes. Without a synced catalog, these features have nothing to work with.

This guide covers the available sync methods and their trade-offs.

# Sync methods overview

User.com supports multiple ways to sync your product catalog:

Method Best for Update frequency
XML feed (recommended) Full catalog sync, bulk updates Daily (automatic, at night). To sync more frequently, use the API trigger method described below.
REST API Real-time updates, individual products On-demand
CSV import Bulk updates, adding custom attributes Manual or scheduled
Frontend events Supplementary updates from user browsing Real-time

We recommend the XML feed as your primary sync method. It handles bulk updates efficiently, integrates with existing e-commerce infrastructure (most platforms already generate Google Shopping feeds), and ensures complete catalog coverage.

The other methods serve as supplements—use REST API for real-time price or stock changes, CSV for one-time enrichment, and frontend events to fill gaps as users browse.


An XML product feed synchronizes your entire catalog with User.com in bulk. If you already generate a feed for Google Shopping, you can likely use it directly—or with minor modifications for optimal User.com compatibility.

# Why XML feed is the primary method

  • Complete catalog coverage — All products available for recommendations and personalization from day one
  • Authoritative product data — Prices, availability, and details come from your source of truth
  • Bulk updates — Change thousands of products in a single sync
  • Rich attributes — Sale prices, promotional dates, stock levels, and custom fields for segmentation and dynamic content
  • E-commerce platform compatibility — Most platforms already generate Google Shopping feeds

# Feed format

User.com accepts XML feeds compatible with the Google Merchant Center specification. If you already generate a feed for Google Shopping, you can likely use it directly—or with minor modifications for optimal User.com compatibility.

# Basic structure

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
  <channel>
    <title>Your Store Product Feed</title>
    <link>https://yourstore.com</link>
    <description>Product catalog</description>
    
    <item>
      <g:id>SKU-12345</g:id>
      <g:title>Wireless Bluetooth Headphones</g:title>
      <g:description>Premium noise-canceling headphones with 30-hour battery life</g:description>
      <g:link>https://yourstore.com/products/wireless-headphones</g:link>
      <g:image_link>https://yourstore.com/images/headphones-main.jpg</g:image_link>
      <g:price>149.99</g:price>
      <g:availability>in stock</g:availability>
      <g:brand>AudioTech</g:brand>
      <g:product_type>Electronics > Audio > Headphones</g:product_type>
    </item>
    
    <!-- More items... -->
  </channel>
</rss>

# Required attributes

Every product in your feed should include these core attributes:

Attribute Data Type Description
g:id string Your unique product identifier (SKU or internal ID). Must match the product_id you use in frontend product events.
g:title string Product name as displayed to customers
g:description string Short product description
g:link string Full URL to the product page
g:image_link string URL to the primary product image
g:price number Product price (see Price formatting below)
g:availability string Stock status: in stock, out of stock, preorder, or backorder
g:product_type string Product category path (e.g., Clothing > Women > Dresses)

For products with multiple images, add numbered additional image attributes:

<g:additional_image_link_1>https://yourstore.com/images/headphones-side.jpg</g:additional_image_link_1>
<g:additional_image_link_2>https://yourstore.com/images/headphones-case.jpg</g:additional_image_link_2>
<g:additional_image_link_3>https://yourstore.com/images/headphones-worn.jpg</g:additional_image_link_3>

These attributes enable richer segmentation and personalization:

# Sale and promotional pricing

Attribute Data Type Description
g:sale_price number Discounted price when product is on sale
g:omnibus_price number Lowest price from 30 days before discount (EU Omnibus Directive compliance)
g:sale_price_effective_date string Promotion date range in ISO 8601 format (see below)
g:sale_price_active boolean Whether the sale price is currently active

The sale_price_effective_date follows the Google format with start and end dates separated by a slash:

<g:sale_price_effective_date>2025-02-05T00:00:00+01:00/2025-06-01T23:59:59+02:00</g:sale_price_effective_date>

User.com automatically parses this into separate start and end date attributes.

Important: Either sale_price_effective_date or sale_price_active can be used to determine if a sale price is currently active. See Understanding sync behavior for details.

# Product flags and inventory

Attribute Data Type Description
g:bestseller boolean Flag products as bestsellers
g:new boolean Flag products as new arrivals
g:quantity integer Stock quantity
g:gtin string Global Trade Item Number (EAN/UPC/ISBN)

# Price formatting

This is a common point of confusion. Google Merchant Center feeds typically include a currency suffix:

<!-- Google format - NOT recommended for User.com -->
<g:price>129.99 PLN</g:price>

User.com interprets this as a string, not a number. This breaks:

  • Segmentation: You can't create segments like "products over $50" because text values don't support numeric comparisons (<, >, >=)
  • Dynamic calculations: Snippet Tags and dynamic content can't perform math on text values
  • Price range filters: Any filter requiring numeric operations will fail

Use numeric values without currency:

<!-- Recommended for User.com -->
<g:price>129.99</g:price>
<g:sale_price>99.99</g:sale_price>
<g:omnibus_price>119.99</g:omnibus_price>

Apply this to all price-related attributes: price, sale_price, omnibus_price, and any custom price fields.

# Understanding sync behavior

Product feed synchronization in User.com is append-only. This has important implications:

# What sync does

  • Adds new products that don't exist yet
  • Adds new attributes to existing products
  • Updates the value of existing attributes

# What sync does NOT do

  • Does not remove attributes if they disappear from the feed
  • Does not remove products that are no longer in the feed

# Why this matters: The sale price problem

Consider this scenario:

  1. Monday: Product sync runs. Product has sale_price: 79.99
  2. Wednesday: Promotion ends. You remove sale_price from the feed entirely
  3. Thursday: Sync runs. In User.com, the product still has sale_price: 79.99

The sync saw no sale_price attribute, but absence doesn't mean "delete." The old value persists.

Solution: Use explicit signals instead of attribute presence:

<!-- During promotion -->
<g:sale_price>79.99</g:sale_price>
<g:sale_price_active>true</g:sale_price_active>
<g:sale_price_effective_date>2025-01-01T00:00:00+00:00/2025-01-15T23:59:59+00:00</g:sale_price_effective_date>

<!-- After promotion ends -->
<g:sale_price>79.99</g:sale_price>
<g:sale_price_active>false</g:sale_price_active>

Now your automations and segments can filter on sale_price_active = true instead of checking whether sale_price exists.

# The discontinued product problem

Similar logic applies to product availability:

  1. Monday: Product syncs with availability: in stock
  2. Tuesday: Product is discontinued and removed from your feed entirely
  3. Wednesday: Sync runs. In User.com, product still shows availability: in stock

Solution: Never remove products from the feed. Instead, update their status:

<!-- Mark as unavailable instead of removing -->
<g:availability>out of stock</g:availability>

Or add a dedicated attribute:

<g:active_product>false</g:active_product>

Once a product is marked unavailable in User.com, you can safely remove it from future feed exports.

# Setting up attributes before sync

When a product contains an attribute that doesn't exist in your User.com app, the system creates it automatically with a string data type. This can cause problems for attributes that should be numeric or boolean.

Before your first sync, manually create attributes with the correct data type:

  1. Go to Settings → Workspace Settings → Products → Product attributes
  2. Create each custom attribute with the appropriate type:
Attribute Recommended Type
price, sale_price, omnibus_price etc. Float
sale_price_active, bestseller, new Boolean
sale_price_effective_date Datetime

Standard Google Merchant attributes (id, title, description, link, image_link, availability, brand, product_type) are handled automatically with correct types.

# Configuring your feed

To add a product feed in User.com:

  1. Go to Settings → Workspace settings → Products → Product feeds
  2. Click Add new feed
  3. Enter your feed URL (must be publicly accessible)
  4. Save and run an initial sync

Once configured, the feed will automatically sync once per day at night. To sync more frequently, use the API trigger method described below.

# Feed URL requirements

  • Must be accessible via HTTPS without authentication
  • Should return valid XML with UTF-8 encoding
  • For large catalogs (50,000+ products), consider compressing with gzip

# Triggering feed sync via API

By default, product feeds sync automatically once per day at night. To sync more frequently (e.g., hourly after inventory updates), you can trigger a feed sync programmatically:

curl -X POST \
  "https://YOUR_SUBDOMAIN.user.com/api/public/products/feed_synchronization/FEED_ID/" \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: */*; version=2"

Replace FEED_ID with the numeric ID of your feed (visible in feed settings).

Response:

{"success": "Product feed import has started!"}

This is useful for triggering syncs after bulk inventory updates or price changes in your e-commerce platform. You can set up a scheduled job (e.g., via cron) to call this endpoint hourly or on-demand when your catalog changes.

# Verification

After your first sync:

  1. Go to Data → Products and verify products appear with correct data
  2. Check a few products to confirm:
    • Prices are numeric (not showing currency suffix)
    • Boolean attributes show as true/false toggles
    • Images and links load correctly
  3. Create a test segment using a numeric price filter to confirm comparisons work

# REST API (real-time sync)

Products can be created and updated in real-time using the User.com REST API. Use this method when you need immediate updates—for example, when a product price changes or stock runs out.

# Create a product

Full API reference → (opens new window)

POST /products/

headers = {
  'authorization': "Token <your_64_char_api_key>",
  'Accept': "*/*; version=2",
  'content-type': "application/json"
}
    
body = {
  'custom_id': product_id,
  'attribute': value
}

# Update a product

Full API reference → (opens new window)

PUT /products-by-id/:product_id/

headers = {
  'authorization': "Token <your_64_char_api_key>",
  'Accept': "*/*; version=2",
  'content-type': "application/json"
}
    
body = {
  'attribute': value
}

# CSV import (bulk)

User.com importers allow bulk data imports. Use them for basic synchronization or enriching your product data with additional attributes.

# Manual import via UI

Agents can update the product database by importing CSV files through the User.com interface. While not reliable for maintaining an up-to-date product database, it's useful for:

  • Adding additional custom dimensions (product attributes)
  • One-shot actions and segmentations (e.g., adding a tag to a product group)

# Automated import via REST API

Full API reference → (opens new window)

The same CSV import method is available through the REST API. This can serve as an alternative to the XML product feed or act as a supplementary data source.


# Frontend updates (client-side)

You can use customers browsing your site as a source of product data updates. When a user visits a product page, the frontend event can update product attributes in User.com.

userengage('product_event', {
  product_id: product_id,
  event_type: event_type,
  attribute: value
}); 

Adding attributes in the payload updates the product with those values.

WARNING

Product attributes are updated with the latest values sent. Historical values aren't stored—each new event overwrites the product's profile with the latest information.


# Next steps

With your catalog synced, you're ready to: