Google Shopping and AI agents

Your catalog for shopping engines, AI agents and the Meta, Pinterest and TikTok catalogues: every feed, the field mapping, feed health and rich previews.

Written 2026-09-16. Every Formahand store publishes its own catalog for shopping engines, for the Meta, Pinterest and TikTok catalogues, and for AI shopping agents, with nothing to install and no app to connect. Seven feed files, two agent files, all served by the store itself and always current.

1. What your store publishes

Replace <your store> with your storefront address (myshop.store-on-formahand.app, or your own domain once it is primary):

AddressWhat it is
https://<your store>/feeds/google.xmlThe shopping feed: RSS 2.0 with the g: namespace, the format Merchant Center fetches
https://<your store>/feeds/products.csvThe same rows as a spreadsheet, under Google's own column names
https://<your store>/feeds/products.jsonThe same rows as JSON, for anything you or your agent build
https://<your store>/feeds/meta.csvThe same rows for a Meta catalogue (Facebook and Instagram); see section 6
https://<your store>/feeds/meta.xmlThe Meta rows as RSS, for a catalogue that prefers XML
https://<your store>/feeds/pinterest.xmlThe same rows for a Pinterest catalogue
https://<your store>/feeds/tiktok.csvThe same rows for a TikTok catalogue
https://<your store>/llms.txtYour store written for an AI agent: what you sell, your currency, where you ship, your pages, and how to buy
https://<your store>/.well-known/formahand-store.jsonThe same facts as JSON, plus a pointer to the agent tool endpoint and these docs

All nine are public, need no key, and are cached for ten minutes. The feeds carry X-Robots-Tag: noindex — they are data for a shopping engine, not pages to index — and they are deliberately left out of your sitemap.

Every storefront page also carries one tag in its <head>: a <link rel="alternate" type="application/rss+xml"> pointing at the shopping feed, so a crawler that lands on any page can find the rest. Your store id is published in the two agent documents above, not in a meta tag on every page a shopper loads.

2. One row per buyable item

A plain product is one row. A product with options is one row per variant, and the rows share an item_group_id so a shopping engine groups them as one product with sizes or colours. A product with options but no variant cannot be bought, so it has no row. Archived and unpublished products are never in the feed.

Feed fieldComes from
idThe product id, or the variant id on a variant row
item_group_idThe parent product id; absent on a plain product
titleThe product name, plus the variant title on a variant row (150 characters)
descriptionThe product description as plain text (5,000 characters, markup stripped)
linkhttps://<your store>/products/<slug>, with ?variant=<variant id> on a variant row
image_linkThe variant's photo when it has one, else the product's first photo
additional_image_linkThe rest of the gallery, up to ten
availabilityin stock when stock is above zero, backorder when the product allows backorders, out of stock otherwise
priceThe price, with the currency (19.99 USD). When there is a compare-at price, price is the compare-at and sale_price is what the shopper pays
sale_priceOnly on an item with a compare-at price
brandThe product's vendor, or your store name when it has none
conditionnew
gtinThe barcode, when it is a real GTIN-8/12/13/14. An internal code of your own is left out rather than rejected
mpnYour SKU, from the variant when it has one, else the product
identifier_existsno when the item has neither a GTIN nor a SKU
shipping_weightThe variant's weight, else the product's, in grams. Empty for a digital or service product
product_typeThe product type you typed, else your tags, up to three, joined with >
google_product_categoryGoogle taxonomy ID 4218 (False Nails) for explicit product types Press-on nails, Press on nails, False nails, Fake nails, Artificial nails, or the full Google False Nails category path. Matching ignores case and extra spaces. Other types stay empty; titles and tags are never used to guess a category. Applies to plain products and all their variants across the shopping and channel feeds.

Money is exact: the amount is built from the stored minor units, never from a floating-point multiply, and zero-decimal currencies are written without decimals.

Your product pages carry the same facts as Product structured data — brand, GTIN, SKU, price and availability, including BackOrder — read from the same rows, so the page, the feed and the structured data can never disagree.

3. Adding the feed in Merchant Center

Dashboard → Analytics → Product feeds → Google has the feed address with a copy button and a Check feed button. Then:

  1. Open Merchant Center and pick your store (create an account if this is your first time).
  2. Go to Products → Add products and choose to add them from a file, for the country and language you sell in (menu names to verify: Merchant Center renames them often).
  3. Choose Scheduled fetch as the upload method, not a file upload, so the feed stays current by itself.
  4. Paste https://<your store>/feeds/google.xml as the file URL and let it fetch daily.
  5. Verify and claim your website when asked; your storefront already serves the files that check looks for.

Check feed fetches your live feed the way a shopping engine will and reports how many items it carries, how many are in stock, and the first five problems a shopping engine would reject: no id, no title, no description, no link, no photo, no price. Most rejections are a missing photo or a missing description.

4. For AI shopping agents

https://<your store>/llms.txt follows the llms.txt convention. It names the store, the number of buyable items, the currency, the countries you ship to, every catalog API address, the feed addresses, your published pages, and how a purchase actually happens: send the shopper to the product page, or check out from your own pages with the headless checkout call and your store id. It ends with a pointer to the machine-readable version and to the agent tool endpoint.

An agent that reads it needs nothing else to browse your catalog and quote your prices correctly — the file says in as many words that prices come from the catalog and nowhere else.

Your own agent can work with the feeds through two tools on the agent endpoint: get_feeds returns every address above, the channel feeds included (channelFeeds), and a summary, and check_feed runs the same validation as the dashboard button; check_feed { channel } checks for one channel (see Feed health in section 6). Both need a token with settings:read; GET /api/feeds/check is the same check over HTTP, with ?channel= for one channel.

5. Hidden stores

A store with Hide store from search switched on (Online Store → Search & sharing) serves 404 on all nine addresses. A store that asked not to be indexed is not handed to a shopping engine either, and the head tags are left off its pages. Turn the setting off and the feeds come back at once.

With Let AI assistants read my store switched off (same page), /llms.txt answers 404 and the JSON file no longer points to it; the feeds are unchanged.

The sandbox publishes its own feeds at the sandbox address, and every sandbox page is noindex anyway, so a test catalog never reaches a shopping engine.

While your store is closed behind its password page, every feed and both agent files stay readable, so a shopping engine can fetch them before you open.

6. Channel feeds

The same rows, written the way Meta, Pinterest and TikTok catalogues read them. Paste the address into the channel's catalogue as a scheduled feed.

ChannelAddressFormat
Meta (Facebook and Instagram)https://<your store>/feeds/meta.csvCSV
Meta, as XMLhttps://<your store>/feeds/meta.xmlRSS 2.0 with g: tags, the same rows as the CSV
Pinteresthttps://<your store>/feeds/pinterest.xmlRSS 2.0 with g: tags
TikTokhttps://<your store>/feeds/tiktok.csvCSV

A channel feed follows the rules of sections 1, 2 and 5: the same rows, the same cache, X-Robots-Tag: noindex, and 404 on a hidden store. A row is never left out here: what a channel would reject is reported by the feed check. Text is cut to the channel's limits without splitting a character.

In the dashboard, Analytics → Product feeds shows a tile per channel: Google, Meta, Pinterest and TikTok. A channel's page (#product-feeds/<channel>) has its Feed address with a Copy button, How to add it in three steps, and Feed health with a Check feed button. All four pages share one layout.

Details marked "to verify" come from each channel's public feed specification as we know it. Check them against the channel's own help pages before relying on them.

Tracking

Every link in a channel feed carries utm_source=<channel>&utm_medium=feed, where the channel is meta, pinterest or tiktok. A variant link keeps its ?variant= and gains the two parameters after it. A parameter the link already has is never added twice. The shopping feed at /feeds/google.xml is unchanged and carries no tracking parameters.

Variants

As in section 2, a product with options is one row per active variant. Each row has the variant id as its id (sku_id on TikTok), the product id as item_group_id, the variant title in its title ("Tee - Red / M"), and the variant's own price, sale price, stock and photo (the product's photo when the variant has none). A plain product has an empty item_group_id and no ?variant= in its link.

The link is https://<your store>/products/<slug>?variant=<variant id> plus the tracking. The product page opens with that variant chosen.

When a product has an option named Colour (or Color) or Size, its value (up to 100 characters) goes in the channel's color or size field. Other option names are not sent. The two CSV columns appear at the end only when some row has a value, so a catalogue without them keeps exactly its columns. /feeds/products.json carries every option of a variant row as options: [{ "name": "Size", "value": "M" }]; the shopping feed and its CSV do not change.

Availability

Our stock stateMetaPinterestTikTok
In stockin stockin stockin stock
Out of stockout of stockout of stockout of stock
Backorder allowedavailable for order (to verify)preorder (to verify)available for order (to verify)

Meta

ColumnRequiredLimit or rule
idyes100 characters
titleyes150 characters (newer docs say 200, to verify)
descriptionyes9,999 characters, plain text
availabilityyesin stock or out of stock; see the table above
conditionyesnew
priceyesAmount, a space, the ISO currency: 12.00 USD, 1200 JPY, 1.250 KWD
linkyesThe product page, with tracking
image_linkyesAt least 500 x 500 px (we cannot measure this in the feed)
brandyes100 characters
sale_pricenoSame format as price
additional_image_linknoUp to 20, comma separated in the CSV, one tag each in the XML
item_group_idnoThe product id on a variant row
gtin, mpn, product_type, google_product_categorynoAs in the shopping feed
color, sizenoFrom a Colour or Size option, 100 characters (to verify); only when some row has one

The CSV columns, and the XML tags, come in the order above.

Pinterest

Pinterest reads the same RSS shopping format as /feeds/google.xml, with g: prefixed tags, in this order: id, title, description, link, image_link, additional_image_link, availability, price, sale_price, condition, brand, gtin, mpn, product_type, google_product_category, item_group_id, color, size. How it differs from the shopping feed:

FieldPinterestShopping feed
availabilityin stock, out of stock, preorder; no backorder, so a backorder is written preorder (to verify)also backorder
titleUp to 500 characters, but Pinterest shows far fewer150
descriptionUp to 10,000 characters5,000
additional_image_linkUp to 10 (to verify), one tag eachUp to 10
priceMust carry the ISO currency codeSame
identifier_existsNot used, left outWritten as no when there is no GTIN or SKU
shipping_weightLeft outWritten for a physical product
linkMust be on the website you claimed in your Pinterest business account; carries trackingNo tracking
idUp to 127 characters (to verify)No cap
color, sizeFrom a Colour or Size optionNot written

Images: at least 500 x 500 px (to verify); Pinterest recommends tall images.

TikTok

ColumnRequiredLimit or rule
sku_idyesThe product id, or the variant id on a variant row
titleyes255 characters (to verify)
descriptionyes10,000 characters (to verify), plain text
availabilityyesin stock, available for order, preorder, out of stock (to verify)
conditionyesnew
priceyesAmount, a space, the ISO currency
linkyesThe product page, with tracking
image_linkyesAt least 500 x 500 px
brandyesThe vendor, or your store name
sale_pricenoSame format as price
item_group_idnoThe product id on a variant row
additional_image_linknoUp to 10, comma separated (to verify)
gtin, mpn, product_type, google_product_categorynoAs in the shopping feed
color, sizenoFrom a Colour or Size option (to verify); only when some row has one

The CSV columns come in the order above.

Feed health

The feed check for one channel (Check feed on the channel's page, GET /api/feeds/check?channel=google|meta|pinterest|tiktok, or the check_feed tool with channel) reads /feeds/products.json once and lists, per row, what that channel would reject or warn about. Each issue carries a one-sentence fix and a link to the product in the dashboard. A reject means the channel drops the item; a warning means it shows the item, but worse.

CheckGoogleMetaPinterestTikTok
No idrejectrejectrejectreject
No titlerejectrejectrejectreject
Title longer than the channel shows (150, 150, 500, 255)warnwarnwarnwarn
Empty descriptionrejectrejectrejectreject
No product linkrejectrejectrejectreject
Variant row whose link does not pick the variant (?variant=)rejectrejectrejectreject
No price, or a zero pricerejectreject (zero: to verify)reject (zero: to verify)reject (zero: to verify)
No photorejectrejectrejectreject
Photo smaller than the channel wants (100, 500, 500, 500 px; to verify)warnwarnwarnwarn
No brand, no barcode and no SKUwarnwarnwarnwarn

The check is ok only when the feed has rows and no row is rejected. rejected and warned count rows; the first 50 issues are listed and issueCount has the total.

Photo sizes: the store does not record them, so the check reads the size of the main photos of the first 20 rows with a distinct photo, only photos on your store's own address, reading just the first 64 KiB of each. A photo it cannot read that way is skipped, and other photos are not checked. imagesMeasured says how many were read.

Known limits:

  • The feed already cuts titles to 150 and descriptions to 5,000 characters, so a title warning shows up only where a channel's limit is lower than that, and no channel feed carries a longer description.
  • The feed carries at most ten extra photos per row, though Meta accepts 20.
  • The feed uses your store name as the brand when a product has no vendor, so the brand warning is rare.

7. Rich previews

When someone shares or pins a product page, Meta and Pinterest read the page itself: its Open Graph tags and its product structured data (JSON-LD). Pinterest calls a pin that shows the live price and stock a rich pin.

The product page's Open Graph product tags:

TagValue
product:price:amount, product:price:currencyThe list price, as in the feeds: the compare-at price when the product is on sale, else the price. "12.00", "1200" for JPY, "1.250" for KWD
product:sale_price:amount, product:sale_price:currencyOnly on sale: the price the shopper pays
product:availabilityin stock, out of stock or available for order (a backorder; to verify)
product:conditionnew
product:brandThe vendor, else the store name; no tag when both are empty
product:retailer_item_idThe product id, the feed row id of a plain product
product:item_group_idOnly for a product with variants: the product id, the feeds' item_group_id (to verify that Meta matches on it)
og:price:amount, og:price:currencyFor Pinterest: the price the shopper pays now (to verify)
og:price:standard_amountFor Pinterest, only on sale: the list price (to verify)
og:availabilityFor Pinterest: instock, out of stock or backorder (to verify)

A product with variants shows its lowest variant price and is in stock when any variant is, the same as its structured data. A gift card is always in stock.

Rich pin readiness

What Pinterest reads (to verify against Pinterest's current rich pin help) and whether the product page has it:

FieldOn the pageWhere
Product nameyesJSON-LD Product
Product descriptionyesJSON-LD Product
Product imageyesJSON-LD Product, every product photo
Product urlyesJSON-LD Product, the page's own address
Product brandyesJSON-LD Product: the vendor, else the store name
Product skuyes, when the product has oneJSON-LD Product
Product gtinyes, when the barcode is a real oneJSON-LD Product
Offer price, priceCurrencyyesJSON-LD Offer (AggregateOffer with low and high price for variants)
Offer availabilityyesJSON-LD Offer
Offer urlyesJSON-LD Offer
aggregateRatingnoReviews are not read while the page is built
og:type productyesOpen Graph
og:title, og:description, og:site_nameyesOpen Graph
og:urlyes, when the page has a canonical addressOpen Graph
og:imageyesThe first product photo, or the page's own share image
og:image:width, og:image:heightnoPhoto sizes are not recorded
Price amount and currencyyesOpen Graph product tags above
AvailabilityyesOpen Graph product tags above

The structured data and the Open Graph tags both carry what a product rich pin needs.

Share image

The share image is the product's first photo. The page would prefer the first photo at least 1200 px wide, but the store does not record photo sizes, so it keeps the first photo. Upload your best wide photo first.

See also

Connect an existing Google Merchant Center account

In Analytics → Product feeds → Google, connect your Google account with Merchant Center permission, then choose Find my Merchant Center accounts. Select the existing account for this store and confirm the connection. Formahand checks that its HTTPS homepage matches the store’s current primary domain. It does not change or take over website claims. Only signed-in store owners/admins can link accounts or register a feed; Test mode cannot submit products.

Choose a sales country you can fulfill orders to, the actual two-letter language of the product content and the feed label. Review feed setup checks the current public Google feed and existing primary sources without submitting products. Confirm the displayed account, market and fulfillment readiness to register a daily scheduled fetch of /feeds/google.xml. A matching existing source is reused with its existing schedule. Overlapping primary/API/automatic sources and duplicate exact sources block creation for reconciliation; there is no automatic replacement or product deletion. Uncertain create responses remain held across restarts until a matching source can be confirmed.

Refresh Google diagnostics reads the account’s homepage claim, product sources, account-level issues and latest registered feed processing. Failed/unavailable checks remain distinct from success. Processing success is not proof of individual product approval; per-product eligibility, shipping, returns, business information and free-listing setup remain in Merchant Center. The manual feed instructions remain available when a direct connection cannot be completed. Keep a single primary source for the same product identity and market.

Disconnect this store’s link removes Formahand’s local connection only. It does not delete the merchant’s account, products or scheduled Google feed, and does not disconnect the shared Google login. Pause ingestion in Merchant Center when needed. Removing the authorizing person’s store role, switching their Google identity, revoking Google access or changing the primary domain stops delegated operations until reauthorization/reconciliation.

The connection is stored as merchant_owned with the existing Merchant Center ID and source name. Later approved platform account-management relationships can attach to that same account; MCA approval does not automatically migrate merchants. This release does not create MCA subaccounts, establish provider relationships or switch hosted feeds to API product uploads. Those changes need a separately reviewed flow that preserves account/product identity and avoids competing writers.

Agents can call get_google_shopping { refresh: false } for the selected store’s saved link or { refresh: true } for Google diagnostics, with settings:read and current owner/admin membership for the token creator. There are no agent tools for granting account access or enabling ingestion; those actions stay with the signed-in owner/admin.

Platform prerequisites: configure Google authorization, enable Merchant API in its Google Cloud project, complete the one-time Merchant API developer registration and configure Google OAuth consent for the https://www.googleapis.com/auth/content permission. Developer registration is distinct from advanced-account/MCA approval. It applies to the Cloud project once, not to each connected merchant. Google can require OAuth application verification or testing-user restrictions before general merchant access is available.

Official references: account discovery, data sources, file processing, developer registration, future account-management relationships.