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

# Publisher Configuration

> Configure ad pacing, contextual serving, creative constraints, and experiments using the config object.

> [!WARNING]
>
> **v1 is deprecated.** New integrations should use [v2](https://docs.thrad.ai/api/api-reference/bid-request-v2.md).

The `config` object lets you control how ads are served per request — pacing, contextual serving, creative constraints, and analytics tags. All fields are optional and fall back to defaults set on your publisher in the platform dashboard.

```json theme={null}
{
  "config": {
    "ad_offset": 3,
    "max_frequency": 5,
    "contextuality": 2,
    "retargeting_enabled": true,
    "max_headline_chars": 60,
    "image_enabled": true,
    "restricted_click_area": false,
    "redirect_after_vote": false,
    "experiment_tag": "variant_a"
  }
}
```

## Ad Pacing

Controls when and how often ads appear in a conversation. Two checks run before any auction logic:

* **Ad Offset** (`ad_offset`) — minimum turns before the first ad in a conversation
* **Max Frequency** (`max_frequency`) — minimum number of requests between consecutive ads

When pacing blocks a request, the API returns a `200 OK` with `"bid": null` and a message indicating the reason — same as a no-bid. Continue without an ad.

| Field | Type | Description |
| - | - | - |
| `ad_offset` | `int` | Min turn number before first ad. `null` uses dashboard default. `0` disables the offset check. |
| `max_frequency` | `int` | Min requests between consecutive ads. For example, `5` means an ad can appear at most once every 5 requests. `null` uses dashboard default. `0` disables the frequency check. |

### Example

```json theme={null}
{
  "config": {
    "ad_offset": 3,
    "max_frequency": 5
  }
}
```

This says: "Don't show ads before turn 3, and require at least 5 requests between consecutive ads." The system tracks request counts automatically.

## Contextual Serving

Controls how an ad is matched to the conversation. Independent of pacing — these settings affect *whether* a relevant ad is found, not *when* it can appear.

### Contextuality

`contextuality` sets how closely an ad must match the conversation before it can be served, on a `1`–`8` scale (default `2`).

**Higher contextuality requires a stronger match, so fewer requests return an ad (lower fill rate) but each ad is more on-topic. Lower contextuality is more permissive and returns ads more often.** Tune it to trade relevance against fill.

| Field | Type | Description |
| - | - | - |
| `contextuality` | `int` (1–8) | How strict the contextual match must be. Higher = stricter match and lower fill rate; lower = more permissive, higher fill. `null` uses dashboard default (`2`). |

### Retargeting

`retargeting_enabled` (default `true`) lets a relevant ad reach a user again based on their recent activity. When enabled, if a product was contextually relevant to a user in a conversation within the last **7 days**, it can be shown to that user again — even if the current conversation isn't relevant to that product. Set it to `false` to serve only ads relevant to the current conversation.

| Field | Type | Description |
| - | - | - |
| `retargeting_enabled` | `bool` | Allow re-proposing a recently-relevant ad (within the last 7 days) to the same user, even when the current conversation isn't relevant to it. `null` uses dashboard default (`true`). |

### Example

```json theme={null}
{
  "config": {
    "contextuality": 5,
    "retargeting_enabled": false
  }
}
```

This says: "Only serve highly on-topic ads (stricter match, lower fill), and don't retarget — restrict ads to the current conversation."

## Creative Constraints

Control what the ad creative looks like to fit your UI.

### Headline Limit

When `max_headline_chars` is set, the system guarantees no headline exceeds the limit. If no creative fits, no ad is returned.

```json theme={null}
{
  "config": {
    "max_headline_chars": 50
  }
}
```

### Image Control

When `image_enabled` is `false`, the response is forced into text mode: `placement` is `"text"`, the `image_url` field is omitted entirely, and an advertiser logo is returned in `logo_url` instead. Render the logo on your card. Use this when your UI doesn't support product imagery, or when you want a more compact card.

See [Ad Formats & Rendering — Sponsored Message](https://docs.thrad.ai/api/guides/rendering-ads.md#sponsored-message) for the full text-mode vs image-mode response shapes.

```json theme={null}
{
  "config": {
    "image_enabled": false
  }
}
```

### Experimental render directives

> [!NOTE]
>
> Experimental and bespoke — we roll these out with specific publishers we're piloting with. They can be `true` or `false` depending on what you send. If your integration doesn't accommodate them, you can safely ignore the fields.

These flags are echoed back **verbatim** on the bid response so your renderer can act on them. They don't change which ad is served — only how you're advised to render it.

* **`restricted_click_area`** (cards) — when `true`, only specific elements (logo, advertiser name, CTA button) should be clickable rather than the whole card. The value you send is returned on the card bid. Defaults to `false`.
* **`redirect_after_vote`** (polls) — when `true`, send the user to the advertiser (`cta_url`) after they vote; when `false`, stay inline and show the results bar. The value you send is returned on the poll bid. Defaults to `false`.

| Field | Type | Description |
| - | - | - |
| `restricted_click_area` | `bool` | Card render directive, echoed on the response. Default `false`. |
| `redirect_after_vote` | `bool` | Poll render directive, echoed on the response. Default `false`. |

```json theme={null}
{
  "config": {
    "restricted_click_area": true,
    "redirect_after_vote": true
  }
}
```

## Experiments

> [!NOTE]
>
> Beta — available to all publishers.

Use `experiment_tag` to run A/B tests on your integration. Tag each request with a label (max 30 characters) and the tag is recorded on every impression. Compare performance metrics across variants in your dashboard.

| Field | Type | Description |
| - | - | - |
| `experiment_tag` | `string` (max 30 chars) | A/B test label. Recorded on every impression for analytics segmentation. |

### Example

Test whether showing ads after turn 3 vs turn 5 performs better:

```json theme={null}
// Variant A
{ "config": { "ad_offset": 3, "experiment_tag": "offset_3" } }

// Variant B
{ "config": { "ad_offset": 5, "experiment_tag": "offset_5" } }
```

Split your traffic between the two variants and compare `offset_3` vs `offset_5` in your dashboard analytics.

## Maximising Fill Rate

Fill rate is the percentage of bid requests that return an ad. Several factors affect it: conversation relevance, geo targeting, campaign budgets, and pacing settings. Here's a recommended approach:

**Ad quality is the lever, not a bypass.** Fill comes from richer conversation context and sensible pacing, not from asking the server to serve regardless of match.

**Monitor your fill rate** — if you're seeing a fill rate below your target, consider these steps in order:

1. **Lower `ad_offset`** — reduce the number of turns before the first ad. `ad_offset: 0` allows ads from the first exchange.
2. **Lower `max_frequency`** — allow ads more frequently within a conversation.
3. **Remove `max_headline_chars`** — headline constraints filter out some ads. Removing the limit increases the pool of eligible creatives.
4. **Send richer conversation context** — fill follows contextual match quality. More of the exchange, with PII stripped, gives the auction more to match against.

```json theme={null}
// Step 1: Start with normal targeting (recommended)
{ "config": { "ad_offset": 3, "max_frequency": 5 } }

// Step 2: If fill rate too low, relax pacing
{ "config": { "ad_offset": 0, "max_frequency": 2 } }
```

> [!WARNING]
>
> Relaxing pacing raises fill but can lower relevance and click-through rates. Use `config.experiment_tag` to A/B test any change and measure the impact on your metrics before rolling it out fully.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.