Ads & Sponsored Flow
Integrate sponsored product placements across your storefront.
What you'll build
A full ad integration: fetch product listings with sponsored placements mixed in, show personalized sponsored "top picks" on the homepage, display sponsored "cart toppers" on the cart page, and load "frequently bought together" recommendations on the product detail page — all with proper client data for ad targeting.
Prerequisites
- A Store UUID — e.g.
e87437f2-3e35-4738-af5e-6307e368255c(staging) - cURL or any HTTP client
- A product UUID for the FBT (frequently bought together) endpoint
No authentication is required. All sponsored endpoints use
POSTwith a client-data request body for ad targeting.
The Client Data Payload
Every sponsored endpoint requires a POST body with client data used for ad targeting. This is the same structure across all sponsored endpoints:
{
"data": {
"type": "recommendations",
"attributes": {
"url": "https://shop.example.com/products",
"screen": { "height": 1080, "width": 1920 },
"navigator": {
"user_agent": "Mozilla/5.0 ...",
"language": "en-US"
},
"mobile": false,
"account_id": null,
"site_id": null,
"channel_id": null,
"channel_type": null,
"zone_id": null,
"client_ip": null,
"surfside_domain_id": null,
"session_id": null,
"location_data": {
"zip": "90001",
"country": "US",
"city": "Los Angeles",
"region": "CA",
"utc_offset": "-07:00",
"timezone": "America/Los_Angeles",
"coords": {
"latitude": 34.0522,
"longitude": -118.2437,
"accuracy": null
}
}
}
}
}
Tip: Build a helper that generates this payload from the browser's
navigatorandwindowobjects. The more complete the data, the better the ad targeting.
Step 1: Sponsored Product Listing
Replace your regular GET /api/v1/products call with POST /api/v1/products/sponsored to get product listings that include sponsored placements. The same query parameters (filters, sort, pagination) work here.
cURL
curl -X POST "https://ecom-api.staging.blaze.me/api/v1/products/sponsored?category=flower&limit=10" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-H "X-Store: e87437f2-3e35-4738-af5e-6307e368255c" \
-d '{
"data": {
"type": "recommendations",
"attributes": {
"url": "https://shop.example.com/products?category=flower",
"screen": { "height": 1080, "width": 1920 },
"navigator": { "user_agent": "Mozilla/5.0", "language": "en-US" },
"mobile": false,
"location_data": {
"zip": "90001",
"country": "US",
"city": "Los Angeles",
"region": "CA"
}
}
}
}'
JavaScript (fetch)
const STORE_UUID = "e87437f2-3e35-4738-af5e-6307e368255c";
const BASE_URL = "https://ecom-api.staging.blaze.me";
const headers = {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"X-Store": STORE_UUID,
};
// Build client data from the browser
function buildClientData(currentUrl) {
return {
data: {
type: "recommendations",
attributes: {
url: currentUrl,
screen: { height: window.innerHeight, width: window.innerWidth },
navigator: {
user_agent: navigator.userAgent,
language: navigator.language,
},
mobile: /Mobi/i.test(navigator.userAgent),
account_id: null,
site_id: null,
channel_id: null,
channel_type: null,
zone_id: null,
client_ip: null,
surfside_domain_id: null,
session_id: null,
location_data: null,
},
},
};
}
const params = new URLSearchParams({ category: "flower", limit: "10" });
const response = await fetch(`${BASE_URL}/api/v1/products/sponsored?${params}`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/products?category=flower")),
});
const { data: products, meta } = await response.json();
products.forEach((p) => {
const badge = p.attributes.is_promoted ? "⭐ SPONSORED" : "";
console.log(`${p.attributes.name} — $${p.attributes.unit_price} ${badge}`);
});
Response
{
"data": [
{
"id": "spons-prod-001",
"type": "store_products",
"attributes": {
"name": "Blue Dream",
"slug": "blue-dream",
"type": "Hybrid",
"in_stock": true,
"unit_price": 45.00,
"is_promoted": true
}
},
{
"id": "b5c8d1e2-f3a4-5678-9012-abcdef123456",
"type": "store_products",
"attributes": {
"name": "OG Kush",
"slug": "og-kush",
"type": "Indica",
"in_stock": true,
"unit_price": 40.00,
"is_promoted": false
}
}
],
"meta": {
"total": 20,
"limit": 10,
"offset": 0
}
}
Key field:
is_promoted: truemarks sponsored products. Use this to render a "Sponsored" badge. Organic results haveis_promoted: false.
Step 2: Sponsored User Top Picks
Show personalized recommendations on the homepage with sponsored placements mixed in.
cURL
curl -X POST "https://ecom-api.staging.blaze.me/api/v1/products/recommendations/sponsored-user-top-picks?limit=8" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-H "X-Store: e87437f2-3e35-4738-af5e-6307e368255c" \
-d '{
"data": {
"type": "recommendations",
"attributes": {
"url": "https://shop.example.com/",
"screen": { "height": 1080, "width": 1920 },
"navigator": { "user_agent": "Mozilla/5.0", "language": "en-US" },
"mobile": false,
"location_data": null
}
}
}'
JavaScript (fetch)
const topPicksRes = await fetch(
`${BASE_URL}/api/v1/products/recommendations/sponsored-user-top-picks?limit=8`,
{
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/")),
}
);
const { data: topPicks } = await topPicksRes.json();
console.log("🏠 Homepage — Top Picks for You:");
topPicks.forEach((p) => {
const badge = p.attributes.is_promoted ? " [Sponsored]" : "";
console.log(` ${p.attributes.name} — $${p.attributes.unit_price}${badge}`);
});
Response
{
"data": [
{
"id": "top-pick-001",
"type": "store_products",
"attributes": {
"name": "Gelato",
"slug": "gelato",
"type": "Hybrid",
"in_stock": true,
"unit_price": 50.00,
"is_promoted": true
}
},
{
"id": "top-pick-002",
"type": "store_products",
"attributes": {
"name": "Wedding Cake",
"slug": "wedding-cake",
"type": "Hybrid",
"in_stock": true,
"unit_price": 55.00,
"is_promoted": false
}
}
],
"meta": {
"total": 8,
"limit": 8,
"offset": 0
}
}
Fallback: If no ad data is available for the user, the endpoint falls back to organic recommendations (same products, all with
is_promoted: false).
Step 3: Sponsored Cart Toppers
Show add-on suggestions on the cart page with sponsored products.
cURL
curl -X POST "https://ecom-api.staging.blaze.me/api/v1/products/recommendations/sponsored-cart-toppers?limit=4" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-H "X-Store: e87437f2-3e35-4738-af5e-6307e368255c" \
-d '{
"data": {
"type": "recommendations",
"attributes": {
"url": "https://shop.example.com/cart",
"screen": { "height": 1080, "width": 1920 },
"navigator": { "user_agent": "Mozilla/5.0", "language": "en-US" },
"mobile": false,
"location_data": null
}
}
}'
JavaScript (fetch)
const cartToppersRes = await fetch(
`${BASE_URL}/api/v1/products/recommendations/sponsored-cart-toppers?limit=4`,
{
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/cart")),
}
);
const { data: cartToppers } = await cartToppersRes.json();
console.log("🛒 Cart Page — You might also like:");
cartToppers.forEach((p) => {
console.log(` ${p.attributes.name} — $${p.attributes.unit_price}`);
});
Response
{
"data": [
{
"id": "topper-001",
"type": "store_products",
"attributes": {
"name": "Rolling Papers",
"slug": "rolling-papers",
"in_stock": true,
"unit_price": 5.00,
"is_promoted": true
}
},
{
"id": "topper-002",
"type": "store_products",
"attributes": {
"name": "Grinder",
"slug": "grinder",
"in_stock": true,
"unit_price": 25.00,
"is_promoted": false
}
}
],
"meta": {
"total": 4,
"limit": 4,
"offset": 0
}
}
Step 4: Frequently Bought Together (FBT)
On the product detail page, show products commonly purchased with the current product.
cURL
PRODUCT_ID="b5c8d1e2-f3a4-5678-9012-abcdef123456"
curl -X POST "https://ecom-api.staging.blaze.me/api/v1/products/recommendations/frequently-bought-together/$PRODUCT_ID?limit=4" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-H "X-Store: e87437f2-3e35-4738-af5e-6307e368255c" \
-d '{
"data": {
"type": "recommendations",
"attributes": {
"url": "https://shop.example.com/products/blue-dream",
"screen": { "height": 1080, "width": 1920 },
"navigator": { "user_agent": "Mozilla/5.0", "language": "en-US" },
"mobile": false,
"location_data": null
}
}
}'
JavaScript (fetch)
const productId = "b5c8d1e2-f3a4-5678-9012-abcdef123456";
const fbtRes = await fetch(
`${BASE_URL}/api/v1/products/recommendations/frequently-bought-together/${productId}?limit=4`,
{
method: "POST",
headers,
body: JSON.stringify(
buildClientData(`https://shop.example.com/products/blue-dream`)
),
}
);
const { data: fbtProducts } = await fbtRes.json();
console.log("🔗 Frequently Bought Together:");
fbtProducts.forEach((p) => {
const badge = p.attributes.is_promoted ? " [Sponsored]" : "";
console.log(` ${p.attributes.name} — $${p.attributes.unit_price}${badge}`);
});
Response
{
"data": [
{
"id": "fbt-001",
"type": "store_products",
"attributes": {
"name": "Pre-Roll Cones",
"slug": "pre-roll-cones",
"in_stock": true,
"unit_price": 8.00,
"is_promoted": false
}
},
{
"id": "fbt-002",
"type": "store_products",
"attributes": {
"name": "Rolling Papers",
"slug": "rolling-papers",
"in_stock": true,
"unit_price": 5.00,
"is_promoted": true
}
}
],
"meta": {
"total": 3,
"limit": 4,
"offset": 0
}
}
Distinguishing Organic vs Sponsored
All sponsored endpoints return the same product shape as organic endpoints. The only difference is the is_promoted field:
function renderProductCard(product) {
const { name, unit_price, main_image, is_promoted } = product.attributes;
return {
name,
price: unit_price,
image: main_image,
badge: is_promoted ? "Sponsored" : null,
};
}
// Use the same renderer for both organic and sponsored results
const { data: organic } = await (
await fetch(`${BASE_URL}/api/v1/products?limit=10`, { headers })
).json();
const { data: sponsored } = await (
await fetch(`${BASE_URL}/api/v1/products/sponsored?limit=10`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData(window.location.href)),
})
).json();
// Both return the same structure — is_promoted is the only difference
console.log("Organic:", organic.map(renderProductCard));
console.log("Sponsored:", sponsored.map(renderProductCard));
Putting It All Together
const STORE_UUID = "e87437f2-3e35-4738-af5e-6307e368255c";
const BASE_URL = "https://ecom-api.staging.blaze.me";
const headers = {
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json",
"X-Store": STORE_UUID,
};
function buildClientData(url) {
return {
data: {
type: "recommendations",
attributes: {
url,
screen: { height: 1080, width: 1920 },
navigator: { user_agent: "Mozilla/5.0", language: "en-US" },
mobile: false,
location_data: null,
},
},
};
}
// 1. Homepage — sponsored top picks
const { data: topPicks } = await (
await fetch(`${BASE_URL}/api/v1/products/recommendations/sponsored-user-top-picks?limit=8`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/")),
})
).json();
console.log(`Homepage: ${topPicks.length} top picks (${topPicks.filter((p) => p.attributes.is_promoted).length} sponsored)`);
// 2. Category page — sponsored product listing
const { data: listing } = await (
await fetch(`${BASE_URL}/api/v1/products/sponsored?category=flower&limit=10`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/products?category=flower")),
})
).json();
console.log(`Category: ${listing.length} products (${listing.filter((p) => p.attributes.is_promoted).length} sponsored)`);
// 3. Product detail — frequently bought together
const productId = listing[0]?.id;
if (productId) {
const { data: fbt } = await (
await fetch(`${BASE_URL}/api/v1/products/recommendations/frequently-bought-together/${productId}?limit=4`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData(`https://shop.example.com/products/${productId}`)),
})
).json();
console.log(`FBT: ${fbt.length} related products`);
}
// 4. Cart page — sponsored cart toppers
const { data: toppers } = await (
await fetch(`${BASE_URL}/api/v1/products/recommendations/sponsored-cart-toppers?limit=4`, {
method: "POST",
headers,
body: JSON.stringify(buildClientData("https://shop.example.com/cart")),
})
).json();
console.log(`Cart toppers: ${toppers.length} suggestions`);
What's Next?
- Organic recommendations (without ads): Use
GET /api/v1/products/recommendations/user-top-picksandGET /api/v1/products/recommendations/cart-toppers— see the Ads & Recommendations guide - Product browsing: See the Browsing Flow example
- Cart & checkout: See the Cart & Checkout guide