Catalog Ads
Run Advantage+ catalog ads from a Meta product catalog with goal catalog_sales, and find the catalog and product set to promote.
Promote items from a Meta product catalog with goal: "catalog_sales" on POST /v1/ads/create. One ad covers N items: Meta renders the visuals per catalog item and picks which product or vehicle each person sees. Two discovery endpoints find the catalog and the product set first. You need the same accountId and adAccountId as any other create, and the ad account needs a pixel.
Catalog contents live in Meta Commerce Manager or a feed provider. Zernio reads the catalogs and runs ads on them; it does not edit items.
Find the catalog and product set
Catalogs hang off the ad account's business. Call GET /v1/ads/catalogs to list them.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: catalogs } = await zernio.adcreatives.listAdCatalogs({
query: { accountId: '66b2e19d8c3f5a7e9d0b1c2d', adAccountId: 'act_1234567890' }
});
const catalogId = catalogs.catalogs[0].id;Response (200):
{
"catalogs": [
{ "id": "1003405825408877", "name": "Vehicle inventory", "vertical": "vehicles", "productCount": 132 }
]
}Then list that catalog's product sets. The product set, not the catalog, is what the ad promotes.
const { data: sets } = await zernio.adcreatives.listAdCatalogProductSets({
path: { catalogId: '1003405825408877' },
query: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' }
});
const productSetId = sets.productSets[0].id;Response (200):
{
"productSets": [
{ "id": "1003260032095191", "name": "All vehicles", "productCount": 132 }
]
}Create the catalog campaign
goal: "catalog_sales" builds the whole chain: a Sales-objective campaign, an ad set bound to the product set, and a catalog template creative. There is no imageUrl and no video, because Meta renders the visuals from the catalog items.
The copy fields become the template and accept Meta's catalog template tags ({{product.name}}, {{product.price}}, and on a vehicle catalog {{vehicle.make}}, {{vehicle.model}}, {{vehicle.year}}, {{vehicle.price}}), so each rendered item carries its own data.
const { data: created } = await zernio.adcampaigns.createStandaloneAd({
body: {
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
adAccountId: 'act_1234567890',
name: 'Vehicle inventory, catalog',
goal: 'catalog_sales',
budgetAmount: 30,
budgetType: 'daily',
headline: '{{vehicle.year}} {{vehicle.make}} {{vehicle.model}}',
body: 'Find your next car',
description: '{{vehicle.price}}',
callToAction: 'LEARN_MORE',
linkUrl: 'https://example.com/inventory',
countries: ['US'],
optimizationGoal: 'OFFSITE_CONVERSIONS',
promotedObject: {
productSetId: '1003260032095191',
pixelId: '1729525464415281',
customEventType: 'PURCHASE'
}
}
});Response (201), trimmed:
{
"ad": {
"_id": "66d4a1b2c3e4f5a6b7c8d9e6",
"status": "pending_review",
"goal": "catalog_sales",
"platformObjective": "OUTCOME_SALES",
"optimizationGoal": "OFFSITE_CONVERSIONS",
"promotedObject": {
"productSetId": "1003260032095191",
"pixelId": "1729525464415281",
"customEventType": "PURCHASE"
}
}
}All 3 promotedObject fields are required. Meta's "Promoted Object is Required" error on a catalog ad set usually means the pixel is missing, not the product set.
How it behaves
Targeting works like any other campaign: countries, age, gender, placements and saved audiences all apply. Broad targeting is fine here, because Meta matches items to people; layer retargeting off pixel events with optimizationGoal: "OFFSITE_CONVERSIONS".
The ad set optimization defaults to LINK_CLICKS, which would buy clicks for a campaign asking Meta for purchases, so the sample sends the top-level optimizationGoal: "OFFSITE_CONVERSIONS" to optimize toward the customEventType in promotedObject (conversion campaigns).
catalog_sales is a single-creative shape. It cannot be combined with creatives[], adSetId, dynamicCreative or placementAssets, because the catalog template is already the multi-item mechanism.
Catalog creatives need an explicit Instagram identity for Instagram placements. When the connected Page has no linked Instagram account, Zernio falls back to the Page-backed one. Meta has retired the legacy PRODUCT_CATALOG_SALES objective on modern ad accounts, so Zernio uses the current Sales-objective shape.
Common errors
A 400 names the field that conflicts with the catalog shape:
{
"error": "creatives is not supported with goal catalog_sales",
"type": "invalid_request_error",
"param": "creatives"
}Send one creative. Zernio checks promotedObject.productSetId before creating anything: passing the catalog id where the product set id belongs, or a set the token cannot read, returns a precise 400 naming promotedObject.productSetId rather than a raw Meta error. A productCatalogId that does not contain the set names promotedObject.productCatalogId instead. If the catalog or product set id belongs to another business, Meta's own 400 comes back inside platformError; re-read the ids from the two discovery calls above.
Related
- Campaigns: the base create request.
- Conversion campaigns: every
promotedObjectkey. - Pixels: create the pixel a catalog ad set needs.
- List catalogs and List product sets: every field.
Conversion Campaigns
Optimize a Meta campaign toward a pixel event, an instant form or an app install by adding a promotedObject to the create request.
Messaging & Call Ads
Create Meta ads that open a WhatsApp, Messenger or Instagram Direct conversation with POST /v1/ads/messaging, or dial a number with POST /v1/ads/call.