Skip to content
Docs
FA
Sign in
Start here
  • Overview
  • Quickstart
  • Concepts
Collect data
  • Designing events
  • Event dictionary
  • Placing events
  • Identity
  • Web SDK
  • Android SDK
  • Devices and push
  • Server to server
  • Product catalogue
  • Webhooks
Engage customers
  • Segments
  • Journeys
  • Transactional
  • Consent and caps
  • In-app and inbox
Analyze and export
  • Reports and exports
Developer reference
  • API reference
    • Ingest endpoints
    • Management API
  • Errors
  • Limits
  • OpenAPI
Developer tools
  • MCP server
  • Working with an agent
Privacy and changes
  • Personal data
  • Versioning

The product catalogue: filling it and keeping it true

A scheduled feed, a file upload, and products learned from orders. Three feed formats, the price unit, and the id that produces no recommendations at all if it does not match your events.

The catalogue is your product list as Segmentic sees it: an id, a name, a price, an image, a link and whether it is in stock. While that list is empty the product recommendation block in an email renders nothing at all, with no error anywhere, just a gap. This page is how to fill it and which decisions quietly break it.

#What the catalogue is for

CATALOGUE SOURCES
Product feedScheduled sync
CSV fileManual import
Commerce eventsFill missing items
SEGMENTICProduct catalogueMerge richer sources without downgrading records
PERSONALIZATION
RecommendationsRelevant products
Content blocksName, image and price
Stock triggersAvailability changes
How product feeds, files and commerce events become recommendations and personalized content

Three things, and none of them works without it:

  • The product block in an email, which draws four products in a two-by-two grid.
  • The abandoned cart journey, which has to know what was in the basket before it can show it.
  • The "similar" and "people also bought" recommendations, which stand on the affinity matrix, and that matrix only knows products the catalogue holds.

That last point matters more than it looks. Behaviour comes from your events, but any id that is not in the catalogue is dropped from the recommendation list. So an account with millions of product_viewed events and an empty catalogue produces zero recommendations.

#The id that has to match

This is the most important sentence on the page.

The product id in the catalogue has to be byte for byte what your events send as product_id.

If the site sends SKU-1024 and the feed carries 1024, both halves look correct: the catalogue is full, the events arrive, nothing is wrong in any log, and no recommendation is ever produced. It is the only mistake on this page with no symptom at all.

Before you fill the catalogue, open the Data screen and look at what your events actually send. Then build the feed to match it.

#Three ways to fill it

WayWho it is forHow often
A scheduled feedA shop with a feed URL, or that can produce oneEvery six hours, automatically
A file upload in the panelA small or stable catalogue, or a quick startBy hand
Your shop platform's webhooksAny account with Shopify, WooCommerce or Digikala connectedWith every order

They do not conflict and you can have all three. Which one wins is in from your shop platform.

#The scheduled feed

In the panel: Catalogue, then Product feed. Give it the URL and the format, and turn it on.

From then on it is read every six hours. The result of the last run sits at the top of that screen: how many products it read, when, and if it failed, why. If nothing has succeeded for more than two days the catalogue page raises an alarm, because a feed that stopped quietly is what puts last season's prices in the next campaign.

Three limits worth knowing: each run has two minutes, reads at most 64 megabytes, and takes at most two hundred thousand products from one document.

The feed URL has to be a public one. An address that resolves to your internal network, to localhost or into a private range is refused, and so is a redirect into one. That is deliberate rather than a shortcoming: a server that fetches an address you choose is, without that check, an attack tool pointed at our own network.

The format is never sniffed. Whatever you pick in the form is what gets read, because a guess that comes out wrong once writes a catalogue of garbage over a working one, and it comes out wrong exactly when your platform changes something and nobody is watching.

#The CSV format

The first row has to be column names. These are recognised and anything else is ignored:

FieldAccepted namesRequired
Idsku, id, product_id, codeYes
Nametitle, name, product_nameYes
Priceprice, price_rial, amountTo be shown at all, yes
Price before discountcompare_at_price, old_price, list_priceNo
Categorycategory, product_type, categoriesNo
Brandbrand, manufacturer, vendorNo
Imageimage, image_url, image_linkNo
Product pageurl, link, product_url, permalinkNo
Stockin_stock, stock, availability, quantityNo
Descriptiondescription, descNo

One malformed row does not cost you the file: it is counted and the rest import. If the id column or the name column is missing entirely the whole file is refused, because a file without those two is the wrong file rather than an empty shop.

#The JSON format

Either an array, or an object with a products key:

JSON
{
  "products": [
    {
      "sku": "SHOE-1024",
      "title": "Runner sports shoe",
      "price_rial": 24000000,
      "compare_at_rial": 30000000,
      "category": "Shoes",
      "brand": "Nike",
      "image_url": "https://shop.example.ir/img/1024.jpg",
      "url": "https://shop.example.ir/p/1024",
      "in_stock": true
    }
  ]
}

name for title, id or product_id for sku, image for image_url and link for url are all accepted too.

Leave in_stock out and the product counts as in stock. That is deliberate: a shop exporting only what it sells is the common case, and reading the absence of the field as unavailable would import a catalogue in which nothing can ever be recommended.

#The XML format, meaning Google Merchant

If your shop publishes a feed for the price comparison sites, it is probably already this one and you have nothing new to build.

XML
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <item>
      <g:id>SHOE-1024</g:id>
      <g:title>Runner sports shoe</g:title>
      <g:price>24000000 IRR</g:price>
      <g:sale_price>19000000 IRR</g:sale_price>
      <g:availability>in stock</g:availability>
      <g:image_link>https://shop.example.ir/img/1024.jpg</g:image_link>
      <g:link>https://shop.example.ir/p/1024</g:link>
      <g:brand>Nike</g:brand>
      <g:product_type>Shoes</g:product_type>
    </item>
  </channel>
</rss>

When sale_price is present and lower than price, it is the price and price becomes the struck-through "was" line. availability takes the specification's own values, and out of stock is the only one that makes a product unavailable.

XML is the one format that carries its own currency, which makes it the lowest-risk of the three.

#Prices, and their unit

Prices are stored in rial and rendered in messages in toman.

This is the one place where a silent mistake puts a wrong number in front of your customers, so the rule is strict:

FormatHow it is read
CSV and JSONThe number is assumed to be rial. If your file is in toman, multiply by ten in the file.
XML with IRRRial
XML with IRT or TOMANMultiplied by ten
XML with any other currencyStored with no price

That last row is on purpose. A product with no price is visible in the panel and absent from every message, which is a gap somebody finds. A price ten times wrong is a number nobody questions and somebody orders against.

Separators do not matter: 24000000, 24,000,000 and 24.000.000 all read as the same number.

A product priced at zero is never recommended. If the catalogue is full and the recommendations are empty, look at the price column first.

#Stock, and a product that leaves the feed

A product that is out of stock never appears in a message. Recommending something that is not for sale is, at the scale of a campaign, a click into a dead end multiplied by the whole send.

A product that is absent from the next run is marked unavailable, not deleted. Deleting it would lose the affinity history it appears in and it would come back with tomorrow's first order anyway. Marking it keeps the row in the panel, which is where somebody notices that half a catalogue went quiet.

There is also a guard worth knowing about. If one run reads less than half of what the last successful run read, the products it did read are written and nothing is marked unavailable. A truncated file, a login page where the feed should be, or an export that stopped half way must not be able to empty a working catalogue at three in the morning.

#Uploading a file in the panel

On the Product feed screen, below the feed settings. Give it a CSV, correct the columns it guessed, and see how many products were built and what price the first one got before anything is sent.

Two things this screen has that the feed does not: you choose the price unit right there (toman or rial), and a duplicate id inside one file is reported with its row number.

A large file is chunked for you and you watch the progress. If it fails part way it stops and tells you how many landed, because an import somebody believes is complete is worse than one that visibly failed.

#Previewing a recommendation for one user

At the bottom of the Catalogue screen, the preview is always available. After two characters, the same query searches user ids, mobile numbers and email addresses together. For example, 09 finds phones containing it as well as ids or emails containing 09. Matching users appear immediately below the search field. Select one person, leave the recommendation priority on automatic or choose a specific priority, then inspect the result before sending.

If a phrase matches several users, the panel shows each result as a card. Selecting one removes the other cards and keeps the chosen person visible. That choice matters because recommendations come from that user's own behaviour history, and silently taking the first match could preview somebody else's result.

#From your shop platform

If you have connected Shopify, WooCommerce or Digikala, every order that arrives already carries the ids, names and prices of what was bought. Those go into the catalogue on their own, with nothing to configure.

With one rule that matters: a webhook only fills a gap and never overwrites anything. An order line knows the least about a product of any source: no image, no category, no compare-at price. So if a feed or a file wrote that product already, the order leaves it alone. The other way round, a shop with a correct feed would watch its catalogue get slightly worse with every order placed.

The currency is read from the platform's own field. If it names one we do not recognise, the product is stored with no price, exactly as with a feed.

Cancellations and returns teach nothing. A returned item is still a real product, but a payload that exists to undo something is a poor first sighting of one, and the next real order carries the same lines.

#Syncing from your backend

For an automated sync, publish the catalogue as a JSON feed at an HTTPS URL and add that URL in the panel. Segmentic fetches the feed on schedule and shows the latest run status on the same screen.

#Quick troubleshooting

SymptomMost likely cause
Catalogue full, recommendations emptyThe ids do not match the events' product_id. See the id
Some products are never recommendedTheir price is zero, or they are out of stock
Every price is ten times too highA toman file read as rial. See prices
The feed saves but I see no runsIt is not enabled, or its URL is private and was refused. The error is at the top of that screen
The feed health card says "Needs attention"Nothing has succeeded for more than two days. The reason is in last_error on the Feed screen
Products went unavailable yesterdayThey left the feed. If that was not intended, look at the feed

#What to read next

  • Placing events if you do not send product_viewed and order_completed yet. Without them a full catalogue still has no history to recommend from.
  • The event dictionary for an online shop's event list.
  • Journeys for building the abandoned cart.
PreviousServer to serverNextSegments

On this page

  • What the catalogue is for
  • The id that has to match
  • Three ways to fill it
  • The scheduled feed
  • The CSV format
  • The JSON format
  • The XML format, meaning Google Merchant
  • Prices, and their unit
  • Stock, and a product that leaves the feed
  • Uploading a file in the panel
  • Previewing a recommendation for one user
  • From your shop platform
  • Syncing from your backend
  • Quick troubleshooting
  • What to read next

Segmentic

This page is written from the code