Meta Ads
Meta Ads provider
Section titled “Meta Ads provider”The Meta provider registers as meta and manages website conversion
measurement plus a complete paused website conversion campaign graph: Pixel/Dataset
binding, Custom Conversion, campaign, ad set, external-media ad creative, and
serving ad. Credentials come from the environment. The Agoraform CLI remains
provider-neutral; there is no Meta-specific command.
See the complete Meta website conversion campaign example for a reusable paused workflow, import, destroy ordering, and Ads Manager verification before enabling delivery.
Source at tag v0.6.0.
Runtime configuration
Section titled “Runtime configuration”Credentials and connection details come from environment variables:
META_ACCESS_TOKEN required Meta Marketing API access tokenMETA_AD_ACCOUNT_ID required Ad account ID (`act_123...` or bare numeric ID)Tokens never belong in the manifest, logs, plan output, or local state.
Prefer a Meta Business system-user access token with ads_management for
automation. Agoraform consumes an existing token; it does not create Meta apps,
Business Manager accounts, system users, or tokens.
META_AD_ACCOUNT_ID accepts either act_123456789012345 or
123456789012345; Agoraform normalizes both to the act_ form.
Declare the provider with an empty configuration block:
providers: meta: {}Connection validation
Section titled “Connection validation”agoraform validate and agoraform plan perform read-only checks when the
manifest declares meta or contains a Meta resource:
- The token reports a granted
ads_managementpermission. - The configured ad account identity is readable.
Both checks use versioned GET requests and do not create, update, or delete any Meta object.
Supported resource graph
Section titled “Supported resource graph”meta.ad├── meta.ad_set│ ├── meta.campaign│ ├── meta.custom_conversion│ │ └── meta.pixel│ └── meta.pixel└── meta.ad_creativeManaged relationships use logical $ref values. External Page, Instagram,
image, and video identifiers remain literal attributes because Agoraform does
not manage those objects.
New campaigns, ad sets, and ads default to PAUSED. Setting ACTIVE is an
explicit manifest change visible in plan.
Money values
Section titled “Money values”dailyBudget, lifetimeBudget, and bidAmount are declared in ad account
currency units. A 20 in a USD account is USD 20.00; a 20 in a JPY account
is 20 yen. Amounts accept at most two decimal places. Agoraform reads the ad
account currency once per run and converts to Meta’s minimum denomination using
Meta’s per-currency offset.
Website conversion measurement
Section titled “Website conversion measurement”meta.pixel
Section titled “meta.pixel”Declares an existing Pixel/Dataset event source by name. Agoraform does not create, rename, or delete Pixels.
- address: meta.pixel.website attributes: name: Websiteagoraform import meta.pixel.website <PIXEL_ID>binds a specific pixel.- An unbound pixel whose
nameuniquely matches one account row is adopted on apply. - Destroy reports the pixel as provider-owned and leaves the remote object.
The declared output pixelId is the numeric Pixel/Dataset id for external
instrumentation (fbq('init', pixelId) or equivalent).
meta.custom_conversion
Section titled “meta.custom_conversion”Creates website Custom Conversions against a managed pixel:
- address: meta.custom_conversion.trial_started attributes: name: Trial Started eventType: START_TRIAL pixel: $ref: meta.pixel.website rule: and: - event: eq: StartTrial defaultValue: 0pixel, rule, and eventType are immutable after creation. Browser Pixel
and Conversions API delivery stay outside Agoraform. Import a Custom Conversion
after the pixel is bound.
Campaign management
Section titled “Campaign management”meta.campaign
Section titled “meta.campaign”- address: meta.campaign.website_acquisition attributes: name: Website Acquisition objective: OUTCOME_SALES status: PAUSED specialAdCategories: [] buyingType: AUCTION adSetBudgetSharingEnabled: falseobjective accepts current ODAX OUTCOME_* values. specialAdCategories is
required; use an empty list when none apply. dailyBudget and lifetimeBudget
are mutually exclusive positive amounts in account-currency units. Omit both for
ad-set budget ownership.
Objective, buying type, and budget ownership/type cannot change in place.
meta.ad_set
Section titled “meta.ad_set”- address: meta.ad_set.instagram_trial attributes: name: Instagram Trial Acquisition status: PAUSED campaign: $ref: meta.campaign.website_acquisition dailyBudget: 50 billingEvent: IMPRESSIONS optimizationGoal: OFFSITE_CONVERSIONS bidStrategy: LOWEST_COST_WITHOUT_CAP destinationType: WEBSITE pixel: $ref: meta.pixel.website customConversion: $ref: meta.custom_conversion.trial_started targeting: countries: [US] publisherPlatforms: [INSTAGRAM] instagramPositions: [FEED, STORIES, REELS]For OFFSITE_CONVERSIONS, both pixel and customConversion are required
and must reference the same pixel. The campaign objective must be
OUTCOME_SALES.
meta.ad_creative
Section titled “meta.ad_creative”Manages deterministic website/link creatives whose media is already in Meta:
- address: meta.ad_creative.instagram_trial attributes: name: Instagram Trial Creative pageId: "123456789012345" instagramUserId: "234567890123456" destinationUrl: https://example.com/trial primaryText: Start organizing your catalog today. headline: Start Your Free Trial callToAction: LEARN_MORE imageHash: "0123456789abcdef0123456789abcdef"Use exactly one external imageHash or videoId. Only name is mutable; to
change copy, destination, CTA, or media, declare a new creative and repoint the
ad.
meta.ad
Section titled “meta.ad”- address: meta.ad.instagram_trial attributes: name: Instagram Trial Ad adSet: $ref: meta.ad_set.instagram_trial creative: $ref: meta.ad_creative.instagram_trial status: PAUSEDname, status, and creative can be updated. The parent adSet is
immutable after creation.
Import and destroy
Section titled “Import and destroy”Import reconstructs managed relationships through the provider-neutral output
catalog. Import dependencies first. A unique output match emits { $ref }; a
missing or ambiguous match fails before state is written.
Destroy follows reverse dependency order. Every remote destroy mutation is a
DELETE; it never activates delivery. Provider-owned pixels remain bound and
make teardown explicitly incomplete.
API version
Section titled “API version”Agoraform v0.6.0 pins all Meta Graph and Marketing API requests to v26.0.
Limitations
Section titled “Limitations”- Agoraform manages Meta configuration objects, not browser Pixel code, Conversions API events, media uploads, or Page/Instagram administration.
RESERVEDbuying type, dynamic creative, catalog ads, existing-post creatives, and arbitrary targeting JSON are not supported.- Offline, app, and non-pixel event sources are rejected for Custom Conversions.
See the manifest reference for every Meta field and the tagged Meta website conversion example.