Reference
Complete signature and types for the JavaScript SDK's unified
requestAd method.
requestAd
Request an ad and render it into a target DOM element.
window.koah.requestAd(request)
Returns Promise<AdResult>.
Types
Full TypeScript signatures for the API surface. Drop these into your project for autocomplete and type-checking.
interface Dimensions {
/** Slot's maximum rendered width in CSS pixels. */
maxWidth?: number
/** Slot's maximum rendered height in CSS pixels. */
maxHeight?: number
}
type ConversationContext = {
type: 'conversation'
question: string
answer?: string
external_conversation_id?: string
}
type ArticleContext = {
type: 'article'
title: string
content: string
about?: string
}
type FeedContext = {
type: 'feed'
text: string
source?: string
description?: string
}
type StaticContext = {
type: 'static'
}
type AdContext =
| ConversationContext
| ArticleContext
| FeedContext
| StaticContext
type PreviewFormat =
| 'card_text_md'
| 'card_text_sm'
| 'card_image_md'
| 'card_image_sm'
| 'image_side_rail_md'
| 'poll_md'
| 'poll_cta_md'
| 'expandable_md'
| 'rabbit_hole_md'
| 'catalog_lg'
| 'catalog_md'
| 'catalog_sm'
| 'quick_pick_md'
| 'budget_finder_md'
interface AdRequest {
target: Element
context: AdContext
dimensions?: Dimensions
experimentTag?: string
slot?: string
previewFormat?: PreviewFormat
signal?: AbortSignal
onFill?: () => void
onNoFill?: () => void
}
interface AdResult {
filled: boolean
fromCache?: boolean
}
type KoahAgeRange =
| 'unknown' | 'under-13'
| '13-15' | '16-17' | '18-20' | '21-24' | '25-29' | '30-34' | '35-39'
| '40-44' | '45-49' | '50-54' | '55-59' | '60-64' | '65-69' | '70-74' | '75+'
type KoahGender = 'unknown' | 'male' | 'female'
type KoahIncomeBracket =
| 'unknown' | '0-50' | '50-100' | '100-150' | '150-200' | '200+'
declare global {
interface Window {
koah: {
requestAd(request: AdRequest): Promise<AdResult>
/** @deprecated Retired. Resolves `false`. Use `requestAd`. */
process(...args: unknown[]): Promise<boolean>
/** @deprecated Retired. Resolves `false`. Use `requestAd`. */
processStaticAd(...args: unknown[]): Promise<boolean>
/** @deprecated Retired. Resolves `false`. Use `requestAd`. */
generateTextAd(...args: unknown[]): Promise<boolean>
setAgeRange(range: KoahAgeRange | { min: number; max: number }): void
setAge(age: number): void
setGender(gender: KoahGender): void
setIncomeBracket(bracket: KoahIncomeBracket): void
}
}
}
AdRequest
The single argument accepted by requestAd.
- Name
- target
- Type
- Element
- Description
DOM element to render the ad into. Calling
requestAdagain with the sametargetcleanly replaces any previously rendered ad in that slot.
- Name
- context
- Type
- AdContext
- Description
Content surrounding the ad, used for contextual matching. See AdContext. Pass
{ type: 'static' }for static placements.
- Name
- dimensions
- Type
- Dimensions
- Description
Maximum rendered dimensions of your slot. Each render format has its own width and height bounds. Koah keeps any render format that fits within
maxWidth×maxHeightand picks from the remaining candidates. Both axes are optional. An omitted axis has no limit. The SDK also limits the width to the target's container and to the viewport. Withoutdimensions, every format that fits the container width is eligible,catalog_lgincluded. See Sizing for mobile and desktop for reading the slot's CSS size at request time.More eligible formats give more fills. Pass
dimensionsonly when your layout limits the space, and give the maximum space available. If you passdimensionssmaller than 240 × 72, the server rejects the request.requestAdresolves{ filled: false }, callsonNoFill, and logs an error in the console. See Sizing & dimensions for the interactive playground and Format Bounds for the full table.window.koah.requestAd({ target: document.getElementById('ad-slot'), context: { type: 'conversation', question, answer }, dimensions: { maxWidth: 480, maxHeight: 300 }, })
- Name
- experimentTag
- Type
- string
- Description
Tag this request with an experiment variant for A/B testing. See Experiments.
- Name
- slot
- Type
- string
- Description
Tag this request with a registered slot name to break down reporting by placement. The slot must be registered in your publisher settings first — passing an unregistered slot rejects the request, resolving with
{ filled: false }and callingonNoFill. See Slots.
- Name
- previewFormat
- Type
- PreviewFormat
- Description
Force a specific ad format for development preview. Takes a render format name such as
card_text_mdorcard_text_sm. Bypasses normal ad selection and returns a specimen ad in the requested format. See Preview Formats.
- Name
- signal
- Type
- AbortSignal
- Description
Cancel an in-flight request. See Request Cancellation.
- Name
- onFill
- Type
- () => void
- Description
Called when an ad is successfully served.
- Name
- onNoFill
- Type
- () => void
- Description
Called when no ad is available. Useful for ad mediation waterfalls.
AdContext
A discriminated union on type. context is required. Pass the shape that matches the content around the ad, or { type: 'static' } for static placements.
conversation
For user/LLM chat surfaces. Omit answer to request an ad alongside the user's question (before the LLM responds), or include it to match against the full exchange.
- Name
- type
- Type
- 'conversation'
- Description
- Name
- question
- Type
- string
- Description
The user's message to the LLM.
- Name
- answer
- Type
- string
- Description
The LLM's response. Optional.
- Name
- external_conversation_id
- Type
- string
- Description
Stable ID for the conversation this message belongs to. Optional.
article
For editorial and long-form content pages.
- Name
- type
- Type
- 'article'
- Description
- Name
- title
- Type
- string
- Description
The article title.
- Name
- content
- Type
- string
- Description
Article body text. Send an excerpt (500–1000 characters), not the full article.
- Name
- about
- Type
- string
- Description
A short description of what the article is about. Optional.
feed
For social feeds, community posts, and similar text surfaces.
- Name
- type
- Type
- 'feed'
- Description
- Name
- text
- Type
- string
- Description
The post or feed item text.
- Name
- source
- Type
- string
- Description
Origin of the post (e.g. community or author name). Optional.
- Name
- description
- Type
- string
- Description
Supplemental description of the post's container. Optional.
static
For placements with no surrounding content: homepages, landing pages, and sidebars.
- Name
- type
- Type
- 'static'
- Description
AdResult
The resolved value of the requestAd promise.
- Name
- filled
- Type
- boolean
- Description
trueif an ad was served and rendered into the target.
- Name
- fromCache
- Type
- boolean
- Description
trueif the response was served from Koah's backend cache rather than freshly ranked. Present only whenfilledistrue.
Format Bounds
See Ad formats for the sizing model. The table below gives the exact pixel bounds of each render format. Pass these names to previewFormat. The suffixes _sm, _md, and _lg mean small, medium, and large.
| Render format | min_width | max_width | min_height | max_height |
|---|---|---|---|---|
card_text_md | 240px | 768px | 200px | 250px |
card_text_sm | 240px | 384px | 72px | 112px |
card_image_md | 240px | 384px | 250px | 250px |
card_image_sm | 240px | 384px | 72px | 112px |
image_side_rail_md | 652px | 880px | 250px | 250px |
poll_md | 288px | 768px | — | 400px |
poll_cta_md | 288px | 768px | — | 460px |
expandable_md | 288px | 768px | — | 400px |
rabbit_hole_md | 320px | 768px | — | 400px |
catalog_lg | 328px | 768px | — | 600px |
catalog_md | 300px | 768px | 250px | 250px |
catalog_sm | 300px | 768px | — | 240px |
quick_pick_md | 300px | 600px | 250px | 250px |
budget_finder_md | 300px | 480px | 300px | 440px |
The minimum slot for any format is 240px wide × 72px tall. If you pass dimensions smaller than 240 × 72, the server rejects the request. requestAd resolves { filled: false }, calls onNoFill, and logs an error in the console.
A previewFormat must fit the slot. Without dimensions, the SDK checks it against 1440 × 550. A catalog_lg preview needs dimensions with maxHeight of 600 or more. Otherwise requestAd throws an error.
Bound values are tied to designer-confirmed format breakpoints and may shift as the renderer evolves. Use them as a guide for slot sizing, not as a contract. The interactive Sizing & dimensions playground stays in sync with the current values.
Retired methods
The v1 methods process(), processStaticAd(), and generateTextAd() are retired. Each one resolves false, calls onNoFill once, makes no request, and warns once in the console.
| Retired method | requestAd context type |
|---|---|
process() | conversation |
processStaticAd() | static |
generateTextAd() | conversation, article, or feed |
See the migration guide for each call.
Request Cancellation
For single-page applications, cancel in-flight ad requests when users navigate away using AbortSignal:
const controller = new AbortController()
window.koah.requestAd({
target: document.getElementById('ad-slot'),
context: { type: 'conversation', question, answer },
signal: controller.signal,
})
// Cancel if user navigates away
controller.abort()
Common pattern for chat apps:
const requestControllers = new Map()
function switchConversation(conversationId) {
// Cancel previous conversation's pending requests
requestControllers.get(currentConversationId)?.abort()
// Create new controller for this conversation
const controller = new AbortController()
requestControllers.set(conversationId, controller)
window.koah.requestAd({
target: document.getElementById('ad-slot'),
context: {
type: 'conversation',
question,
answer,
external_conversation_id: conversationId,
},
signal: controller.signal,
})
}
React / effect-based frameworks: don't abort() from useEffect cleanup.
In development, React Strict Mode runs every effect as setup → cleanup → setup
to surface side-effect bugs. If you tie controller.abort() to the cleanup,
React aborts the request the instant after it starts — you'll see
AbortError: signal is aborted without reason and no ad will render. A
conversation ad request is one-shot: fire it once and only cancel on a genuine
navigation or conversation switch (as above), not on every component teardown.
In React, request once per slot with a ref guard and omit signal unless you're
cancelling on a real route change:
function KoahAd({ question, answer, conversationId }) {
const slotRef = useRef(null)
const requested = useRef(false)
useEffect(() => {
// Assumes the SDK script has loaded — see Installation for gating on
// `window.koah` (or load the script with `defer` instead of `async`).
if (requested.current || !slotRef.current || !window.koah) return
requested.current = true
window.koah.requestAd({
target: slotRef.current,
context: {
type: 'conversation',
question,
answer,
external_conversation_id: conversationId,
},
})
// No abort here: doing so would cancel the request under Strict Mode.
}, [question, answer, conversationId])
return <div ref={slotRef} />
}
Theme tokens
Set these on the theme object (window.koah_init.theme before load, or window.koah.theme at runtime) — see Appearance for usage.
| Token | Type | Default | Description |
|---|---|---|---|
colorScheme | 'light' | 'dark' | auto-detect | Color palette. Defaults to the user's system preference via prefers-color-scheme. |
presentationMode | 'borderless' | 'card' | 'card' | card adds a border and surface background. borderless blends into the host page. |
accentColor | string | '#0d0d0d' | Brand color used for CTA buttons and interactive highlights. |
fontFamily | string | 'inherit' | CSS font-family. 'inherit' uses the host page's font. |
maxWidth | string | '600px' | Maximum width of the ad container. |
Tokens apply consistently across every ad format and are forward-compatible with new formats.
Age range buckets
Strings accepted by setAgeRange for visitor attributes:
Gender values
Strings accepted by setGender for visitor attributes:
Income brackets
Strings accepted by setIncomeBracket for visitor attributes. Values are annual household income in thousands of USD: