You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add ctxSegments() and ctxTargetingKeyValues() for contextual targeting
Introduce a contextual-classification path in the SDK: fetch the DCN's
taxonomy/category classifications for a page URL, cache them on the SDK
instance, and expose a helper that turns the cached response into
GAM-ready targeting key-values.
SDK (lib/sdk.ts, lib/edge/contextual_segments.ts):
- New OptableSDK.ctxSegments(url?) — POSTs to /v1beta1/contextual and
returns ContextualSegmentsResponse { classifications: { categories: [
{ taxonomy, id, score, ... } ] } }. url defaults to
window.location.href. The contextual request fires immediately (does
not await SDK init), so the cache populates as early as possible
during initContextual: true startup. Response is cached on the
instance; calling again refreshes the cache. Pass-through behavior
(no validation / normalization), matching Targeting() at the edge
layer.
- initContextual: true now also fires ctxSegments() at init time
(fire-and-forget, alongside the pageview witness), so the cache is
populated automatically before any consumer reads it.
- New OptableSDK.ctxTargetingKeyValues(taxonomyKeys?) reads the cached
response and returns Record<string, string[]> of category ids grouped
by taxonomy, ready for googletag.pubads().setTargeting(). Without a
map, keys are the raw taxonomy values; with a map, keys are renamed
and only the listed taxonomies are emitted (filter + rename). Ids are
deduped, order preserved.
Tests (lib/sdk.test.ts, lib/test/handlers.ts):
- MSW handler for /v1beta1/contextual.
- Breaking-change tests for ctxSegments and ctxTargetingKeyValues.
- Behavioral coverage: happy path, window.location.href default, empty
/ missing / malformed responses, categories spanning multiple
taxonomies, cache population, default keying, rename, filter of
unmapped taxonomies, and that initContextual: true triggers a
contextual request.
Docs & demos (README.md, demos/**):
- Document the Contextual Segments API in README: ctxSegments() caching
semantics, the initContextual precondition for ctxTargetingKeyValues,
the explicit ctxSegments().then(loadGAM) alternative, key
rename/allow-list, and the requirement that the URL be classified by
the DCN.
- Two new vanilla demo pages —
demos/vanilla/targeting/ctx_segments.html.tpl and
demos/vanilla/nocookies/targeting/ctx_segments.html.tpl — that call
ctxSegments(), render the categories grouped by taxonomy with score
bars, show the derived GAM key-values, and display the raw JSON
response.
- Register both templates in the Makefile demo-html target and link
them from the Audience Targeting section of demos/index.html and
demos/index-nocookies.html.
-[Option 2: Manual Initialization with Commands Queue](#option-2-manual-initialization-with-commands-queue)
@@ -148,7 +150,7 @@ When creating an instance of `OptableSDK`, you can pass an `InitConfig` object t
148
150
When set, enables page context extraction for contextual intelligence. Set to `true` to use defaults, or pass a `PageContextConfig` object to customize what is extracted (HTML content, content selector, max lengths). Extracted context is automatically attached to the first `witness()` call that uses `{ includeContext: true }`.
149
151
150
152
-**`initContextual` (boolean, default: `false`)**
151
-
If `true`, the SDK will automatically fire a `pageview` witness event with full page context during initialization. This is the recommended way to enable contextual pageview tracking without writing custom code. Implies `pageContext: true` when no `pageContext` is explicitly configured.
153
+
If `true`, the SDK will automatically fire a `pageview` witness event with full page context during initialization, and also call `ctxSegments()` to fetch contextual segments for the current page, caching the result on the instance for later use via `ctxTargetingKeyValues()`. This is the recommended way to enable contextual pageview tracking and contextual targeting without writing custom code. Implies `pageContext: true` when no `pageContext` is explicitly configured.
152
154
153
155
-**`consent` (`InitConsent`)**
154
156
Defines the consent settings for data collection and processing.
To reset the context (e.g. on SPA navigation), call `sdk.resetContext()` before the next `witness()` call.
406
408
409
+
### Contextual Segments API
410
+
411
+
In addition to pageview tracking, the SDK can classify a page URL against one or more contextual taxonomies (such as the [IAB Content Taxonomy](https://iabtechlab.com/standards/content-taxonomy/)) and use the result for ad targeting. Call `ctxSegments()` to fetch the contextual classifications for a URL:
412
+
413
+
```javascript
414
+
// Classify the current page (defaults to window.location.href):
Each call to `ctxSegments()` caches its response on the SDK instance (calling it again refreshes the cache). When `initContextual: true`, the SDK calls `ctxSegments()` for you during initialization, so the cache is populated automatically.
432
+
433
+
> **Note:** The requested URL must already have been classified by the DCN. If the DCN has no classification for the URL, the response will contain an empty `categories` array.
434
+
435
+
#### Contextual targeting key-values
436
+
437
+
`ctxTargetingKeyValues(taxonomyKeys?)` reads the cached `ctxSegments()` response and builds a `Record<string, string[]>` of category ids grouped by taxonomy, ready to pass to an ad server such as Google Ad Manager via `googletag.pubads().setTargeting()`.
438
+
439
+
Without arguments, each taxonomy value is used as the key:
Pass a `taxonomyKeys` map to rename keys. Only taxonomies present in the map are emitted (filter + rename), which is useful when you only want to set keys you have configured in your ad server:
A typical Google Ad Manager activation uses a `loadGAM()` helper:
454
+
455
+
```javascript
456
+
// Helper to load GAM ads with optional targeting data:
457
+
varloadGAM=function (tdata= {}) {
458
+
window.googletag=window.googletag|| { cmd: [] };
459
+
googletag.cmd.push(function () {
460
+
for (const [key, values] ofObject.entries(tdata)) {
461
+
googletag.pubads().setTargeting(key, values);
462
+
}
463
+
googletag.pubads().refresh();
464
+
});
465
+
};
466
+
```
467
+
468
+
Because `ctxTargetingKeyValues()` reads the cached response, the instance should be initialized with `initContextual: true` so the segments are fetched during initialization and the cache is likely populated by the time `loadGAM()` runs:
If you are not using `initContextual`, fetch the segments explicitly and call `loadGAM()` once `ctxSegments()` resolves (falling back to an untargeted load on error):
475
+
476
+
```javascript
477
+
optable.cmd.push(function () {
478
+
optable.instance
479
+
.ctxSegments()
480
+
.then(loadGAM)
481
+
.catch((err) => {
482
+
loadGAM();
483
+
});
484
+
});
485
+
```
486
+
487
+
You can also rename and allow-list the GAM keys by passing a `taxonomyKeys` map to `ctxTargetingKeyValues()` (only the taxonomies present in the map are emitted):
488
+
489
+
```javascript
490
+
// Emit only the "iab_ct_3_1" taxonomy, under the GAM key "ctx_iab":
For each [SDK release](https://github.com/Optable/optable-web-sdk/releases), a webpack-generated browser bundle targeting the browsers list described by `pnpm dlx browserslist "> 0.25%, not dead"` can be loaded on a website via a `script` tag.
0 commit comments