OpenAI Ads Manager Campaign Architecture: Budgets, Bids, and Measurement Contracts
OpenAI Ads Manager exposes a campaign hierarchy. Netics explains why its IDs, budgets, bids, creative, and tracking rules form a control contract.
TL;DR
- OpenAI Ads Manager separates campaign intent and budget from ad-group context and bidding, then places the user-facing chat card at the ad level.
- Tracking templates combine across levels with a defined precedence order, while preview is only a rendering check—not proof that an ad can serve.
- Netics recommends paused-first creation, explicit configuration, durable IDs, idempotency keys, and read-backs before activation. The hierarchy is a measurement and control contract, not merely a form.
The form is really a control plane

The useful mental model is not “fill in campaign, ad group, and ad.” It is a dependency graph. A campaign controls the objective, budget, schedule, and targeting shared by its children. An ad group adds context hints and bid configuration. An ad supplies the creative, destination, and file that a person may see. The parent-child relationship determines whether the object can serve at all.
That structure creates an operational contract. The campaign says what outcome and spend boundary matter. The ad group says which context and pricing strategy apply to a cluster. The ad says exactly what is presented and where the click lands. IDs connect those decisions to later reporting. If an integration treats the UI hierarchy as disposable form state, it loses the ability to explain why a click happened, which budget governed it, or which version was reviewed.
The first practical rule is to save returned IDs, not names. Name lookup is exact and case-insensitive, but it can return multiple matches. IDs are the durable handles for updates and reconciliation.
Campaign intent, budget, and bidding belong together
Create the campaign first. Set its status explicitly, preferably paused, and define bidding_type rather than relying on an implicit default. The documented choices are impressions, clicks, and conversions. A conversions campaign also needs an eligible conversion-event setting; selecting the label without configuring a measurable event is not a complete objective.
Budget is not a decorative number. The example uses daily_spend_limit_micros, and the documentation also distinguishes single-resource payloads from bulk-operation payloads. In a bulk campaign input, the example uses max_budget_micros instead. That difference is a warning against copying a dashboard payload into a bulk job without checking the relevant schema.
Campaign targeting is shared by the ad groups below it. A budget change should therefore be treated as a controlled mutation: retrieve the current resource, update the intended field, and read back the result. When changing nested settings or arrays, build the complete desired list. An update that silently replaces targeting is a measurement break, not just a configuration surprise.
At the ad-group level, context_hints describe the context for the group of ads, while bidding_config defines billing and strategy. The documented fixed-bid example sets billing_event_type to click, uses strategy: fixed_bid, and supplies max_bid_micros. The alternative Maximize Results strategy requires omitting that maximum. “Omitting” is meaningful here: sending a field from the other strategy can make the payload invalid or express a different contract than intended.

Chat-card creative has a hard envelope
A standard chat_card has a type, title, body, target URL, and file. The title must contain 3–50 characters. The body cannot exceed 100 characters. The target must be an HTTP or HTTPS URL no longer than 2,048 characters and accessible to OpenAI’s ad crawlers. The image can be uploaded as JPEG, PNG, or WebP and must be at least 640 × 640 pixels; the returned file_id is then used by the ad.
These constraints should be validated before a network request. A short title is not permission to make the body vague, and a valid URL is not proof that the destination will be crawlable. Keep the final creative payload explicit. Updating creative creates a new submitted version and starts another review. The ad also cannot be moved to another ad group, so a creative correction should not be confused with a reassignment operation.
The file, ad group, campaign, and account must belong together. A technically valid image from the wrong account is still an ineligible dependency. Store the creative version, target URL, file ID, and parent IDs as one record in the integration’s own audit trail.
Tracking is a precedence problem
landing_page_configuration.query_string_template can be set at campaign, ad-group, or ad level. Templates from different levels combine. When the same parameter appears more than once, precedence is: the existing destination URL, then the ad, ad group, campaign, and ad account.
This ordering changes how teams should design templates. A campaign-level template can establish stable dimensions such as utm_source=openai and utm_medium=paid. The ad group can add a segment value. The ad can add the creative identifier. But a parameter already present in the destination URL wins over all of them. “Our campaign template owns utm_campaign” is therefore not a safe statement unless the destination is checked too.
Use explicit, non-colliding names where possible, for example utm_campaign={campaign_id}, utm_content={ad_id}, and a click reference such as {oppref} where supported by the documented template. Test the resolved URL at each level and record the expected winner for duplicates. Tracking is part of the contract because it connects serving context to the result in analytics; a beautiful ad with ambiguous attribution is an incomplete system.

Preview is not eligibility
The preview endpoint answers a visual question: does the creative and destination look as expected? The documentation is explicit that a preview does not confirm serving eligibility. Eligibility requires more: review status, account reviews, targeting, budget, serving issues, an active campaign, an active ad group, and an eligible ad.
Use the ad read endpoint with include[]=serving_issues after generating the preview. Check status, review_status, and review, then inspect the parent statuses. An active ad depends on an active ad group and campaign. A paused campaign prevents its child ads from serving, which makes pause a useful safety boundary—not an error to hide.
Idempotency and the paused-first runbook
For single-resource creation, send an idempotency key with the campaign, ad group, and ad requests. For a bulk hierarchy, each create operation has its own key, each operation has a unique operation_id, and same-job parent references use campaign_idempotency_key or ad_group_idempotency_key. If the network response is uncertain, retry with the same job key and body. Reusing the key with a different body returns a conflict.
Bulk jobs can contain up to 1,000 operations and a request body up to 16 MiB. A successful submission returns HTTP 202, but that is only acceptance of the job. Poll until completed, partially_failed, or failed, then read every operation page. With partial failure enabled, successful operations remain successful and there is no rollback. Dependent operations can be skipped after a failed parent.
Our safer sequence is deliberately unglamorous: create the campaign paused; retrieve it; create the ad group paused; retrieve it; upload and validate the file; create the ad paused; preview it; inspect review and serving issues; verify tracking precedence; then activate from parent to child. Keep the idempotency keys, returned IDs, request body hashes, and operation outcomes. If a retry is needed, never improvise a new body under an old key.

Netics’ conclusion
OpenAI’s Ads Manager documentation describes a tidy three-level hierarchy, but its real importance is operational. Objective, budget, bid, context, creative, destination, tracking, review, and serving state are distributed across resources that depend on one another. That is a measurement and control contract.
Treating it as a form encourages defaults, name-based updates, duplicated query parameters, and premature activation. Treating it as a contract produces durable IDs, explicit strategies, reproducible payloads, traceable attribution, and a safe rollback boundary. Start paused, validate the whole chain, and activate only after the evidence—not the preview—says the ad is ready.
For a practical conversation about measurement-led automation, book a Netics audit or visit the Netics homepage.
Sources
- OpenAI Ads Manager — Campaign Management, retrieved 2026-09-17. Primary source for hierarchy, campaign and ad-group settings, chat-card constraints, tracking precedence, preview, serving checks, idempotency, and bulk-operation behavior.
- OpenAI Ads Manager — Bidding & Budgets, retrieved 2026-09-17. Related official reference for budget and bidding configuration.
