> ## Documentation Index
> Fetch the complete documentation index at: https://www.adjar.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Campaign Config Reference

Each campaign in Adjar lives in a TOML file under your `openai/campaigns/` directory (or wherever your [account root](/docs/config/openai/account) points via `imports`). A single file can contain multiple `[[campaigns]]` entries. Adjar reads these files to understand your current campaign setup and writes changes back in the same format — making your entire campaign structure readable and editable by both humans and AI agents.

An OpenAI Ads campaign holds **ad groups**, and each ad group holds **ads**. Budget lives on the campaign; the bid lives on the ad group.

## Full Example

```toml theme={null}
[[campaigns]]
name = "Database Governance | CHATGPT"
status = "active"
bidding_type = "clicks"
daily_budget_usd = 50
locations = [ "1000232" ]
conversion_event_ids = [ "6a57a01958a4819faf9e288c597030dd" ]

[[campaigns.ad_groups]]
name = "Change management"
status = "active"
billing_event = "click"
max_bid_usd = 3.5
context_hints = [
  "Conversations about database schema migrations, SQL review, and production access control.",
]
```

***

## `[[campaigns]]` Fields

<ParamField path="name" type="string" required>
  The campaign's display name. 3–1000 characters. A clear convention (e.g. `<Topic> | CHATGPT`) helps AI agents identify campaigns unambiguously.

  ```toml theme={null}
  name = "Database Governance | CHATGPT"
  ```
</ParamField>

<ParamField path="status" type="string" required>
  Controls whether the campaign is actively serving.

  | Value      | Behaviour                                      |
  | ---------- | ---------------------------------------------- |
  | `"active"` | Campaign is live and eligible to serve         |
  | `"paused"` | Campaign is suspended but retains all settings |

  ```toml theme={null}
  status = "active"
  ```

  `active` and `paused` are the only values you set in config. To remove a campaign, delete its block from TOML — the next `apply` archives the live campaign. (Adjar writes OpenAI's `archived` state during that archive; it is never something you author.)
</ParamField>

<ParamField path="description" type="string">
  An optional free-text internal description for the campaign. Not shown to users — it's a note for you and your AI agent. Omit for none.

  ```toml theme={null}
  description = "Q2 launch — governance messaging, US only"
  ```
</ParamField>

<ParamField path="bidding_type" type="string" default="impressions">
  What the campaign pays for.

  | Value           | Behaviour                            |
  | --------------- | ------------------------------------ |
  | `"impressions"` | Charged per impression (the default) |
  | `"clicks"`      | Charged per click                    |

  ```toml theme={null}
  bidding_type = "clicks"
  ```
</ParamField>

<ParamField path="daily_budget_usd" type="number">
  The campaign's **daily** spend cap, in US dollars. Set exactly one of `daily_budget_usd` or `lifetime_budget_usd` — not both.

  ```toml theme={null}
  daily_budget_usd = 50
  ```
</ParamField>

<ParamField path="lifetime_budget_usd" type="number">
  The campaign's **lifetime** spend cap, in US dollars — the total the campaign may spend over its whole run. Set exactly one of `lifetime_budget_usd` or `daily_budget_usd`.

  ```toml theme={null}
  lifetime_budget_usd = 2500
  ```

  <Note>
    Budgets are expressed in dollars in config; Adjar converts to and from the API's micros (1 USD = 1,000,000 micros) on your behalf.
  </Note>
</ParamField>

<ParamField path="start_time" type="string">
  When the campaign begins serving, as an ISO 8601 timestamp (e.g. `2026-01-01T00:00:00Z`). Omit for no fixed start. Adjar stores the human-readable ISO form and converts to the API's Unix timestamp on write.

  ```toml theme={null}
  start_time = "2026-01-01T00:00:00Z"
  ```
</ParamField>

<ParamField path="end_time" type="string">
  When the campaign stops serving, as an ISO 8601 timestamp. Omit for an open-ended campaign.

  ```toml theme={null}
  end_time = "2026-03-31T23:59:59Z"
  ```
</ParamField>

<ParamField path="locations" type="array of strings">
  An inclusion list of location IDs to target (the API's `targeting.locations.include`). Ads are eligible only in these locations; an empty or omitted list means no location restriction.

  Location IDs are OpenAI's numeric identifiers — e.g. `"1000232"` is the United States. Read them off an imported campaign or the OpenAI Ads dashboard; Adjar passes them through as-is.

  ```toml theme={null}
  locations = [ "1000232" ]
  ```
</ParamField>

<ParamField path="conversion_event_ids" type="array of strings">
  IDs of the conversion events associated with this campaign (the API's `conversion_event_setting_ids`). Reference [conversion event settings](/docs/config/openai/conversions) — declared as `[[conversions]]` or created in the dashboard — by their ID. Order-insensitive.

  ```toml theme={null}
  conversion_event_ids = [ "6a57a01958a4819faf9e288c597030dd" ]
  ```
</ParamField>

***

## `[[campaigns.ad_groups]]`

Ad groups sit inside a campaign and contain ads. Each `[[campaigns.ad_groups]]` entry must appear after the `[[campaigns]]` entry it belongs to. Unlike Google Ads, the **bid lives here**, on the ad group, not on the campaign.

<ParamField path="ad_groups.name" type="string" required>
  The ad group's display name. 3–1000 characters, unique within the parent campaign.

  ```toml theme={null}
  [[campaigns.ad_groups]]
  name = "Change management"
  ```
</ParamField>

<ParamField path="ad_groups.status" type="string" required>
  Whether the ad group is eligible to serve.

  | Value      | Behaviour                                |
  | ---------- | ---------------------------------------- |
  | `"active"` | Ad group is active and its ads can serve |
  | `"paused"` | Ad group is suspended but retained       |

  ```toml theme={null}
  status = "active"
  ```

  As with campaigns, `active` and `paused` are the only values you set; remove the ad-group block to archive it.
</ParamField>

<ParamField path="ad_groups.description" type="string">
  An optional free-text internal description for the ad group. Not shown to users. Omit for none.

  ```toml theme={null}
  description = "Change-management intent"
  ```
</ParamField>

<ParamField path="ad_groups.billing_event" type="string" default="impression">
  The billing event for the ad group's bid (the API's `bidding_config.billing_event_type`).

  | Value          | Behaviour                           |
  | -------------- | ----------------------------------- |
  | `"impression"` | Bid is per impression (the default) |
  | `"click"`      | Bid is per click                    |

  ```toml theme={null}
  billing_event = "click"
  ```
</ParamField>

<ParamField path="ad_groups.max_bid_usd" type="number" required>
  The ad group's maximum bid, in US dollars — the most you'll pay per `billing_event`. Converted to the API's micros on write.

  ```toml theme={null}
  max_bid_usd = 3.5
  ```
</ParamField>

<ParamField path="ad_groups.context_hints" type="array of strings">
  Optional free-text hints describing the audience and conversations this ad group should target inside ChatGPT. Each entry is a natural-language description of intent, topics, and signals. Omit for none.

  ```toml theme={null}
  context_hints = [
    "Conversations about database schema migrations, SQL review, and production access control.",
  ]
  ```
</ParamField>

An ad group holds its ads as a nested array — `[[campaigns.ad_groups.ads]]`. See [Creatives](/docs/config/openai/creatives) for those fields.

***

## Related Pages

* [Account Root](/docs/config/openai/account) — how campaigns are imported via `openai.toml`
* [Creatives](/docs/config/openai/creatives) — the `chat_card` ads nested inside ad groups
* [Conversions](/docs/config/openai/conversions) — the event settings `conversion_event_ids` references
* [OpenAI Ads API access](/docs/openai-ads-api-access) — producing the `openai.json` credentials file
