Zernio
APIFor you
Zernio
APIFor you
Platforms

Meta Ads

Overview

Set up

Connect

Build

CampaignsAd setsCreativesCreative libraryPreviewsBoost a postLead Gen Forms

Target

TargetingCustom Audiences

Ad types

Creative testingConversion campaignsCatalog adsMessaging & call adsClick-to-WhatsApp adsReach & frequency

Measure

InsightsMeta PixelsConversions APIAd URL tracking tags

Operate

Duplicate & lifecycleAccount & ops readsAd LibraryAd comments

Reference

Enums, limits & error codes
Dashboard
OverviewPlatformsAPI ReferenceResources
Meta Ads

Creative testing

Test Meta creative variations by creating N ads inside one ad set with the creatives[] shape on POST /v1/ads/create.


Test creative variations by passing creatives[] on POST /v1/ads/create. You get one campaign, one ad set, and N ads that share a budget, targeting and schedule.

Before you start

You need the same accountId and adAccountId as any other create.

Create N ads in one ad set

The budget stays pooled instead of splitting across parallel ad sets and their learning phases. Meta's delivery algorithm allocates it across the ads inside the single ad set.

creatives[] replaces the top-level headline, body, imageUrl, linkUrl and callToAction. Everything else stays where it was.

import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data: test } = await zernio.adcampaigns.createStandaloneAd({
  body: {
    accountId: '66b2e19d8c3f5a7e9d0b1c2d',
    adAccountId: 'act_1234567890',
    name: 'Spring launch',
    goal: 'traffic',
    budgetAmount: 100,
    budgetType: 'daily',
    countries: ['US'],
    ageMin: 25,
    ageMax: 45,
    creatives: [
      { headline: 'Spring, 30% off', body: 'Limited time.', imageUrl: 'https://cdn.example.com/a.jpg', linkUrl: 'https://example.com/a', callToAction: 'SHOP_NOW' },
      { headline: 'Curated for you', body: 'Our picks.', imageUrl: 'https://cdn.example.com/b.jpg', linkUrl: 'https://example.com/b', callToAction: 'SHOP_NOW' },
      { headline: 'Free shipping', body: 'This week only.', imageUrl: 'https://cdn.example.com/c.jpg', linkUrl: 'https://example.com/c', callToAction: 'SHOP_NOW' }
    ]
  }
});

const adSetId = test.platformAdSetId;

Response (201), trimmed to the first ad:

{
  "platformCampaignId": "120250000000000004",
  "platformAdSetId": "120250000000000005",
  "ads": [
    {
      "_id": "66d4a1b2c3e4f5a6b7c8d9e4",
      "name": "Spring launch #1",
      "status": "pending_review",
      "reviewStatus": "in_review",
      "platformAdSetId": "120250000000000005"
    }
  ]
}

The multi-creative response carries ads[] instead of the single shape's ad. Every entry shares platformCampaignId and platformAdSetId.

Each ad is named "<name> #N", so the request above produces "Spring launch #1" through "Spring launch #3".

Each entry takes video: { url, thumbnailUrl } in place of imageUrl for a video variation (creatives).

Add a variation later

To test a fourth creative without starting a new campaign, pass the ad set's id as adSetId on a fresh POST /v1/ads/create with a single creative.

The new ad joins the ad set and inherits its budget, targeting and schedule. It keeps the learning Meta has already done.

See attach a creative to an existing ad set.

Read the results per creative

Rolled-up metrics land on each ad node of GET /v1/ads/tree, which is enough to rank the variations.

To split a single ad's results by the asset Meta served, use the creative-asset breakdowns: image_asset, video_asset, body_asset, title_asset.

creatives[] is not the same as dynamicCreative. That hands Meta a pool of headlines, bodies and images to recombine inside one ad.

Use creatives[] when you want N distinct ads you can read separately.

If it fails

A 400 means creatives[] was combined with a shape that owns the creative:

{
  "error": "\"creatives\" and \"adSetId\" are mutually exclusive. Use `creatives[]` to create a new campaign with multiple creatives, or `adSetId` to attach a single new creative to an existing ad set.",
  "type": "invalid_request_error",
  "code": "mutually_exclusive_fields",
  "param": "creatives"
}

The same 400 covers placementAssets, carouselCards, existingCreativeId, translations, existingCampaignId and buyingType: "RESERVED".

The top-level headline, body, imageUrl, linkUrl and callToAction are not in that set. This mode ignores them rather than rejecting them, so there is nothing to remove from the request.

Non-Meta platforms return a 400 as well: this shape is Meta only.

Related

  • Campaigns: the base create request.
  • Creatives: video, carousel and per-placement creative shapes.
  • Insights: the breakdowns that attribute results to one asset.
  • Create standalone ad: every field of creatives[].
Was this page helpful?

Custom Audiences

Create Meta customer list, website, lookalike, engagement and saved targeting audiences with POST /v1/ads/audiences, and fill a customer list with hashed uploads.

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.

On this page

Before you startCreate N ads in one ad setAdd a variation laterRead the results per creativeIf it failsRelated