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

# Targeting

> What you tell the SDK about the episode, the viewer and consent, and why each field raises fill and price.

Our ads are contextual: the better the server understands what is on screen and who is watching, the better the match, the fill and the price. The SDK collects the device side itself. Three things come from you.

## The content

`KontextVideo.Content` describes the episode a `VideoAds` is for. Two fields are required; the rest is signal, and every field you add helps.

```swift theme={null}
let content = KontextVideo.Content(
    id: "100001-6",
    language: "en",
    title: "Episode 6",
    duration: 92,
    episodeNumber: 6,
    genre: "romance",
    keywords: ["forced love", "fantasy", "ceo"],
    categories: ["640", "653"],
    mediaRating: .safe,
    url: URL(string: "https://example.com/series/100001/episode/6"),
    series: .init(id: "100001", title: "My Marionette Lover", episodeCount: 40)
)
```

| Field | Why it matters |
| - | - |
| `id`, `language` | Required. The language decides which campaigns are eligible at all. |
| `title`, `description`, `keywords`, `genre` | Contextual matching: a romance drama and a crime series attract different advertisers. |
| `categories` | IAB Content Taxonomy 3.0 ids, the vocabulary advertisers target with. |
| `series` | Lets campaigns follow a series across its episodes; `episodeCount` and `episodeNumber` say where the viewer is in it. |
| `duration` | Sizes the opportunity. |
| `mediaRating` | `.safe` or `.explicit`. Explicit content gets no ads that require safe content. Leave it unset when you don't know; never default it. |
| `url` | The episode's public page, when it has one. |

Times are seconds.

## The viewer

Set what you know on the shared instance whenever you learn it; the next request carries it.

```swift theme={null}
KontextVideo.shared.user = .init(
    id: "user-84213907",
    email: "viewer@example.com",        // or emailHash
    keywords: ["sci-fi", "cooking"]
)
```

* `id` is your own stable identifier for the viewer, used for frequency capping and personalization.
* `email` or `emailHash` improves matching and deduplication across devices. Send the plain address only when the viewer's consent allows it; our server hashes it on arrival and never stores the plain form. Or send the SHA-256 of the normalized address yourself.
* `keywords` are the viewer's interests in your own words.

## Consent

```swift theme={null}
KontextVideo.shared.regulatory = .init(coppa: false)
```

If your app runs a TCF-compliant consent platform, the SDK reads its consent string from the standard shared storage on every request and you set nothing. COPPA cannot be read from the device, so it always comes from you. See [TCF & CMP](https://docs.kontext.so/video/guides/tcf-cmp.md) and [Compliance](https://docs.kontext.so/video/resources/compliance.md).

## What the SDK sends on its own

The device model and OS, locale, screen size and orientation, network type, the advertising identifier when the viewer allowed tracking (see [IFA & ATT](https://docs.kontext.so/video/guides/ifa.md)), your app's bundle id and version, and the content playhead at the time of the request when you gave the SDK your player. None of it needs code from you beyond the ATT setup.

## A/B tests

`KontextVideo.shared.variantId` selects a variant agreed with Kontext, for example to compare two creative styles. Set it before the request you want it on.

## Where to next

> **[IFA & ATT](https://docs.kontext.so/video/guides/ifa.md)**
>
> The one-time setup for the advertising identifier.

> **[API reference](https://docs.kontext.so/video/sdk/swift/api.md#kontextvideo-content)**
>
> Every field of `Content`, `User` and `Regulatory`.


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