Osy#betaRun it on Osyrin: osyrin.com

Reference / API

Product feeds — Google Merchant Center and Meta

GET /feeds/google.xml · GET /feeds/meta.xml — served by Osysharp.Shop

A store built on `Osysharp.Shop` serves its catalogue as product feeds: `/feeds/google.xml` for Google Merchant Center and `/feeds/meta.xml` for Meta's catalogue, both RSS 2.0 in Google's `g:` namespace. One item per size or colour, only listed products, generated from the store's rows every time a channel fetches it.

preview1 example compiled by CIapishopseokit

Summary#

A shopping channel lists your products from a feed: a file it fetches from your store on a schedule. A store built on Osysharp.Shop serves two, the way it serves /sitemap.xml (see [Serve]):

AddressFor
/feeds/google.xmlGoogle Merchant Center (Shopping ads, free listings)
/feeds/meta.xmlMeta's catalogue (Facebook and Instagram shops, dynamic ads)

There is nothing to export and nothing to keep in step. Each fetch is written from the store's rows as they are. Register the address in the channel as a scheduled fetch.

Signature#

[Serve("/feeds/google.xml")] string GoogleProductFeed()
[Serve("/feeds/meta.xml")]   string MetaProductFeed()
string ProductFeed(FeedChannel channel)       // enum FeedChannel { Google, Meta }
Category.GoogleCategory                        // a shelf's place in Google's taxonomy, inherited by its children

Description#

What an item carries#

One item per variant: a customer buys a size or a colour, and a channel shows and prices exactly that. The variants of one product share item_group_id; a product with a single variant is a plain item.

FieldFrom
idthe variant's SKU, else its own id
titlethe product's name and the variant's options: "Loafer (38)"
descriptionthe product's summary, else the start of its description
linkthe product's page (ShopSetup.ProductPath), absolute
image_link, additional_image_linkits photographs, in order
availabilityin stock, or out of stock. A sold-out size stays in the feed and says so
conditionnew
price, sale_price"165.00 SEK". A markdown shows the regular price as price and today's as sale_price
brandthe product's brand
mpnthe SKU
size, colorthe variant's options
product_typethe shelf path: "Coffee > Kenya"
google_product_categoryCategory.GoogleCategory, from the shelf or the nearest one above it
shipping_weightthe variant's packed weight, when known: "250 g"

Only listed products are in a feed, and only those with a price and at least one photograph. Both channels refuse an item without an image. A draft is never listed. Every value is XML-escaped, so a product called Tan & Co <Limited> arrives as text.

Where the two channels differ#

Both channels read the same format: RSS 2.0 with the g: namespace (Google, Meta). They differ in three places, which is why there are two addresses:

GoogleMeta
availabilityin_stock / out_of_stockin stock / out of stock
brandoptional. Without one, or without a SKU, the item says identifier_exists norequired. A product without one gets the shop's own name
extra photographsup to 10up to 20

Placing shelves in Google's taxonomy#

Google sorts products by its own product taxonomy. Set a shelf's GoogleCategory to the taxonomy's number ("187") or its path ("Apparel & Accessories > Shoes"). Every product on that shelf and on the shelves under it is sent with it. Staff set it with the rest of the shelf.

Examples#

Placing a shelf in Google's taxonomy from the desk#

app FeedsExample {
  use Osysharp.Shop@1 { egress "api.resend.com"; secret "ResendApiKey"; }
  model "model/**/*.osy";
}

using Osysharp.Shop;

/// Puts a shelf in Google's taxonomy. Its products, and those on the shelves under it, are sent with it.
[Authorize(IsShopStaff)]
public void PlaceShelf(Category shelf, string taxonomy) {
  shelf.GoogleCategory = taxonomy;
  UnitOfWork.Commit();
}

One item, as Google reads it#

<item>
  <g:id>GG-KIAMBU-AA-1000</g:id>
  <g:title>Kiambu AA (1 kg)</g:title>
  <g:description>The product’s summary, as the shop wrote it.</g:description>
  <g:link>https://groundsandgrapes.example/p/kiambu-aa</g:link>
  <g:image_link>https://groundsandgrapes.example/files/products/kiambu-aa.jpg</g:image_link>
  <g:availability>in_stock</g:availability>
  <g:condition>new</g:condition>
  <g:price>560.00 SEK</g:price>
  <g:brand>Grounds &amp; Grapes</g:brand>
  <g:mpn>GG-KIAMBU-AA-1000</g:mpn>
  <g:item_group_id>4b0c…</g:item_group_id>
  <g:size>1 kg</g:size>
  <g:product_type>Coffee</g:product_type>
</item>

See also#

Related

[Serve]

Gives a function an address on the app's own origin. A GET at that address answers with the function's return value as…

The SEO kit — schema.org structured data for a page's head

`Osysharp.Seo` ships schema.org's shapes as classes: a product with its offer, rating and brand, an article, a…

The analytics kit — Plausible or Google Analytics 4, with consent

`Osysharp.WebAnalytics` reports an app's page views and e-commerce events to Plausible or Google Analytics 4. The app…