feat: add ctxSegments() and ctxTargetingKeyValues() for contextual targeting#292
Merged
Conversation
898d702 to
32583d0
Compare
zapo
reviewed
Jun 3, 2026
63ad5d2 to
1def934
Compare
mosherBT
reviewed
Jun 3, 2026
Contributor
mosherBT
left a comment
There was a problem hiding this comment.
The cache here never gets cleared? Which means navigating on a site will reuse the cached contextual info? Say if we navigate on the page to a different article the contextual info never gets repopulated? We are treating the page context cache like targetingData cache but I think they need to have different behaviours.
I think we should at the very least have a ClearCache function to reload on changes.
mosherBT
approved these changes
Jun 3, 2026
MO-Thibault
approved these changes
Jun 3, 2026
zapo
approved these changes
Jun 3, 2026
1def934 to
4ffb1c0
Compare
…rgeting
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 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 is widened from boolean to
boolean | ((response: ContextualSegmentsResponse) => void). When
truthy (true or a function), the SDK fires a pageview witness and
ctxSegments() at init time (fire-and-forget), so the cache is
populated automatically before any consumer reads it. When set to a
function, the SDK additionally invokes the callback with the
ContextualSegmentsResponse once it resolves — useful for chaining an
ad-server load (e.g. GAM) on the contextual response without making
a second ctxSegments() call. The callback is not invoked if the
request fails.
- 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, that initContextual: true triggers a contextual
request, and that initContextual as a function triggers the request
and invokes the callback with the response.
Docs & demos (README.md, demos/**):
- Document the Contextual Segments API in README: ctxSegments() caching
semantics, the initContextual precondition for ctxTargetingKeyValues,
the boolean | callback union type, the callback-driven loadGAM
pattern, 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. Both pages document the initContextual callback pattern
in the intro section and in the GAM activation section.
- 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.
4ffb1c0 to
b66f2e7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a contextual-classification path to the SDK: fetch the DCN's
taxonomy/category classifications for a page URL, cache them on the SDK
instance, and turn the cached response into GAM-ready targeting key-values.
What's new
SDK methods (
lib/sdk.ts,lib/edge/contextual_segments.ts)OptableSDK.ctxSegments(url?)— POSTs to/v1beta1/contextualand returns
ContextualSegmentsResponsewith shape{ classifications: { categories: [{ taxonomy, id, score, ... }] } }.urldefaults towindow.location.href. The response is cached onthe instance; calling again refreshes the cache. Pass-through
behavior (no validation / normalization), matching
Targeting()atthe edge layer.
OptableSDK.ctxTargetingKeyValues(taxonomyKeys?)— reads thecached response and returns
Record<string, string[]>of categoryids grouped by taxonomy, ready for
googletag.pubads().setTargeting(). Without a map, keys are the rawtaxonomy values; with a map, keys are renamed and only the listed
taxonomies are emitted (filter + rename). Ids are deduped, order
preserved.
initContextualis widened frombooleantoboolean | ((response: ContextualSegmentsResponse) => void). Whentruthy, the SDK fires a pageview witness and
ctxSegments()at inittime (fire-and-forget), so the cache is populated automatically
before any consumer reads it. When set to a callback function, the
SDK additionally invokes the callback with the response once
ctxSegments()resolves — useful for chaining an ad-server load(e.g. GAM) on the contextual response without making a second
ctxSegments()call. The callback is not invoked if the requestfails.
Tests (
lib/sdk.test.ts,lib/test/handlers.ts)/v1beta1/contextual.window.location.hrefdefault,empty / missing / malformed responses, categories spanning multiple
taxonomies, cache population, default keying, rename, filter of
unmapped taxonomies, that
initContextual: truetriggers acontextual request, and that
initContextualas a function triggersthe request and invokes the callback with the response.
Docs & demos
ctxSegments()caching semantics, the
initContextualprecondition forctxTargetingKeyValues(), theboolean | callbackunion type, thecallback-driven
loadGAMpattern, the explicitctxSegments().then(loadGAM)alternative, key rename/allow-list,and the requirement that the URL already be classified by the DCN.
demos/vanilla/targeting/ctx_segments.html.tplanddemos/vanilla/nocookies/targeting/ctx_segments.html.tpl— callctxSegments(), render categories grouped by taxonomy with scorebars, show the derived GAM key-values, and display the raw JSON
response. Both pages document the
initContextualcallback patternin the intro section and in the GAM activation section.
demo-htmltarget andlinked from the Audience Targeting section of
demos/index.htmlanddemos/index-nocookies.html.Files changed
11 files, +1173 / −6.