Shoppable widgets
Turn library videos into shoppable storefront experiences: tag products on videos, build onsite widgets (Stories, Carousel, Spotlight, For You Feed, Tile, Collection Grid, Bubble Feed), publish them, and read Meta ads performance. All via the Tolstoy Library MCP.
Mental model
- A video becomes shoppable when you tag store products on it (
tag_video_product). Tagged videos feed the product_tagged playlist and show on those products' pages.
- A widget (onsite project) is what shoppers see on the store — it draws from playlists/rules and renders as Stories, Carousel, Spotlight, etc.
- A widget is live in Tolstoy when
live: true, but storefront visibility also needs the Tolstoy app embed enabled in the Shopify theme (one-time, per store). The publish result spells out the steps — relay them.
- Tools default to the connected store; pass
appUrl (full or a distinctive fragment) to target another of the account's stores. Use list_stores to see them.
Make a video shoppable
- Find the video —
search_assets (by name) or list_assets (recent/favorites).
- Find the product —
search_products with the product title → take its externalProductId.
- Tag it —
tag_video_product { vodAssetId, addProductIds: [externalProductId], appUrl? }. Untag with removeProductIds.
- The result reports per-product success/failure — if a product id belongs to another store, it fails; pass the matching
appUrl.
Build & publish a widget
- Create —
create_widget { type } where type is stories, carousel, spotlight, tv (For You Feed), tile-embed, collectionPageTile, or bubble-feed. It starts offline with the platform's defaults (most start from product-tagged videos).
- Inspect —
get_widget { publishId } shows the actual media it will render, content rules, and PDP mode. For PDP-mode widgets, pass productId to see exactly what a given product page would show.
- Adjust —
update_widget { publishId, ... }: rename, toggle isPdpMode, set maxMediaAgeDays, or replace content (sourcesIn/sourcesOut playlists, rules for pin/hide/manual/sort). Read with get_widget first; these are full replacements.
- Publish —
update_widget { publishId, live: true }. Relay the returned app-embed setup steps; confirm whether the embed is already enabled on the store.
Read ad performance
list_ad_campaigns — Meta campaigns with real delivery status. Report effectiveStatus, not just status; ACTIVE-but-not-delivering is not "live."
get_ads_performance { level, datePreset } — spend, ROAS, CTR, purchases. Use level: "ad" for winner/loser creative comparisons. If purchases are 0 but custom conversions exist, the account tracks conversions differently — don't call it unprofitable.
publish_to_meta_ads_library { asset } — push a library video/image into Meta Ads Manager, ready for ad creation. No campaign or spend is created. With multiple ad accounts, pass adAccountId.
There is no create/activate/pause-campaign tool — money-moving operations stay in the Tolstoy platform on purpose.
End-to-end example
"Make my unboxing video shoppable for the DBTK 1 shirt, put it in a stories widget, publish it, and show me how my ads are doing."
search_assets "unboxing" → vodAssetId
search_products "DBTK 1" → externalProductId
tag_video_product { vodAssetId, addProductIds: [externalProductId] }
create_widget { type: "stories" } → publishId
get_widget { publishId, productId: "<DBTK 1 id>" } → confirm the video shows on that product's page
update_widget { publishId, live: true } → relay app-embed steps
get_ads_performance { level: "campaign", datePreset: "last_7d" }
Notes
- Multi-store: a product id is store-specific. Keep
appUrl consistent across search_products and tag_video_product.
get_widget content is the unscoped pool unless you pass productId; PDP-mode widgets show only the per-product subset to shoppers.
- App-aware clients (ChatGPT, Claude) render a shoppable-widget card grid and media previews inline.
1---2name: shoppable-widgets3description: Shoppable widgets4---56# Shoppable widgets78Turn library videos into shoppable storefront experiences: tag products on videos, build onsite widgets (Stories, Carousel, Spotlight, For You Feed, Tile, Collection Grid, Bubble Feed), publish them, and read Meta ads performance. All via the Tolstoy Library MCP.910## Mental model1112- A **video** becomes **shoppable** when you tag store **products** on it (`tag_video_product`). Tagged videos feed the `product_tagged` playlist and show on those products' pages.13- A **widget** (onsite project) is what shoppers see on the store — it draws from playlists/rules and renders as Stories, Carousel, Spotlight, etc.14- A widget is **live** in Tolstoy when `live: true`, but storefront visibility also needs the Tolstoy app embed enabled in the Shopify theme (one-time, per store). The publish result spells out the steps — relay them.15- Tools default to the **connected store**; pass `appUrl` (full or a distinctive fragment) to target another of the account's stores. Use `list_stores` to see them.1617## Make a video shoppable18191. Find the video — `search_assets` (by name) or `list_assets` (recent/favorites).202. Find the product — `search_products` with the product title → take its `externalProductId`.213. Tag it — `tag_video_product { vodAssetId, addProductIds: [externalProductId], appUrl? }`. Untag with `removeProductIds`.22 - The result reports per-product success/failure — if a product id belongs to another store, it fails; pass the matching `appUrl`.2324## Build & publish a widget25261. **Create** — `create_widget { type }` where type is `stories`, `carousel`, `spotlight`, `tv` (For You Feed), `tile-embed`, `collectionPageTile`, or `bubble-feed`. It starts **offline** with the platform's defaults (most start from product-tagged videos).272. **Inspect** — `get_widget { publishId }` shows the actual media it will render, content rules, and PDP mode. For PDP-mode widgets, pass `productId` to see exactly what a given product page would show.283. **Adjust** — `update_widget { publishId, ... }`: rename, toggle `isPdpMode`, set `maxMediaAgeDays`, or replace content (`sourcesIn`/`sourcesOut` playlists, `rules` for pin/hide/manual/sort). Read with `get_widget` first; these are full replacements.294. **Publish** — `update_widget { publishId, live: true }`. Relay the returned app-embed setup steps; confirm whether the embed is already enabled on the store.3031## Read ad performance3233- `list_ad_campaigns` — Meta campaigns with real delivery status. Report `effectiveStatus`, not just `status`; ACTIVE-but-not-delivering is not "live."34- `get_ads_performance { level, datePreset }` — spend, ROAS, CTR, purchases. Use `level: "ad"` for winner/loser creative comparisons. If purchases are 0 but custom conversions exist, the account tracks conversions differently — don't call it unprofitable.35- `publish_to_meta_ads_library { asset }` — push a library video/image into Meta Ads Manager, ready for ad creation. No campaign or spend is created. With multiple ad accounts, pass `adAccountId`.3637There is **no** create/activate/pause-campaign tool — money-moving operations stay in the Tolstoy platform on purpose.3839## End-to-end example4041> "Make my unboxing video shoppable for the DBTK 1 shirt, put it in a stories widget, publish it, and show me how my ads are doing."42> 1. `search_assets "unboxing"` → vodAssetId43> 2. `search_products "DBTK 1"` → externalProductId44> 3. `tag_video_product { vodAssetId, addProductIds: [externalProductId] }`45> 4. `create_widget { type: "stories" }` → publishId46> 5. `get_widget { publishId, productId: "<DBTK 1 id>" }` → confirm the video shows on that product's page47> 6. `update_widget { publishId, live: true }` → relay app-embed steps48> 7. `get_ads_performance { level: "campaign", datePreset: "last_7d" }`4950## Notes5152- Multi-store: a product id is store-specific. Keep `appUrl` consistent across `search_products` and `tag_video_product`.53- `get_widget` content is the unscoped pool unless you pass `productId`; PDP-mode widgets show only the per-product subset to shoppers.54- App-aware clients (ChatGPT, Claude) render a shoppable-widget card grid and media previews inline.