@elo-ads/web-sdk
v0.2.0
Published
The Elo web SDK for rendering in-chat, conversation-aware ads in React apps. It fetches an ad for the current conversation, renders it as a native card, and handles render + viewable-impression tracking for you.
Readme
@elo-ads/web-sdk
The Elo web SDK for rendering in-chat, conversation-aware ads in React apps. It fetches an ad for the current conversation, renders it as a native card, and handles render + viewable-impression tracking for you.
The product is Elo (elo.ad). This is the JS/web SDK, a sibling to the iOS and Android SDKs.
Install
npm install @elo-ads/web-sdkIt's a browser package and must be consumed through a bundler (Vite, Next.js,
webpack) — it is not meant to run in plain Node. react and react-dom
(v18 or v19) are peer dependencies.
Quick start
import { EloSDK, EloAd } from '@elo-ads/web-sdk'
import type { AdCreative } from '@elo-ads/web-sdk'
import { useEffect, useState } from 'react'
const sdk = new EloSDK({
publisherId: 'YOUR_PUBLISHER_ID',
adUnitId: 'YOUR_AD_UNIT_ID',
backendUrl: 'https://api.withgrowl.com',
})
export function ChatAd({ messages }: { messages: { role: 'user' | 'assistant' | 'summary'; content: string }[] }) {
const [ad, setAd] = useState<AdCreative | null>(null)
useEffect(() => {
sdk.init().then((result) => {
if (result.status !== 'ready') return // e.g. 'gdpr_consent_missing'
sdk.fetchAds({ messages }).then((res) => setAd(res.ad))
})
}, [])
// No-fill: when `ad` is null, render nothing.
return ad && <EloAd sdk={sdk} ad={ad} />
}<EloAd> fires the render event on mount and a viewable impression once the
card has been ≥50% visible for 1 second — you don't fire any tracking yourself.
API
new EloSDK(config: EloConfig)
| Field | Type | Required | Description |
| ------------- | ----------- | -------- | ------------------------------------------------------ |
| publisherId | string | Yes | Your Elo publisher ID. |
| adUnitId | string | Yes | The ad unit to request. |
| backendUrl | string | Yes | Elo ad server URL (e.g. https://api.withgrowl.com). |
| coppa | 0 \| 1 | No | COPPA flag passed through to the ad server. |
| tfua | 0 \| 1 | No | "Tag for users under age of consent" flag. |
sdk.init(): Promise<InitResult>
Resolves the visitor ID (localStorage → cookie → generated), starts a session,
and reads consent signals. Returns { status: 'ready' } when ad requests can
proceed, or { status: 'gdpr_consent_missing' } when GDPR applies but no TCF
consent string is present (don't request ads in that case). Call once before
fetchAds.
sdk.fetchAds(params: FetchAdsParams): Promise<AdResponse>
interface FetchAdsParams {
messages: { role: 'user' | 'assistant' | 'summary'; content: string }[]
context?: { type: string; description: string }[]
}Requests an ad for the current conversation. Send the full message history for
the most relevant ad, or — for long conversations — a single summary-role
message plus the most recent turns. The response is:
interface AdResponse {
request_id: string
ad: AdCreative | null // null on no-fill
ecpm: number | null
}Throws if the request fails (non-2xx response).
<EloAd sdk={sdk} ad={ad} className? style? />
React component that renders an AdCreative and handles render + impression
tracking. Accepts an optional className and inline style.
Styling
The card exposes stable class hooks you can target:
.elo-ad— the card container.elo-ad-image— the creative image.elo-ad-title— the title text.elo-ad-description— the description text.elo-ad-sponsored— the "Sponsored" label
Privacy
The SDK reads IAB consent signals (TCF, GPP) from localStorage and forwards
them with each ad request; enforcement happens server-side. You can also pass
coppa / tfua flags via EloConfig. See the
Elo docs for details.
License
Apache-2.0 © 2026 Adapt Research, Inc. See LICENSE and NOTICE.
