@velocityio/web-sdk
v0.11.0
Published
Velocity's web SDK to integrate with Web applications
Readme
Velocity Web SDK
Velocity's web SDK for integrating contextual ads into web applications.
- Full documentation: https://docs.velocity.io/web/integration-guide
- API reference: https://docs.velocity.io/web/api-reference
- Changelog: https://docs.velocity.io/web/changelog
Installation
npm install @velocityio/web-sdkQuick Start
import { VelocitySDK } from '@velocityio/web-sdk';
const sdk = new VelocitySDK({ publisherKey: 'YOUR_PUBLISHER_KEY' });
const initResult = await sdk.init();
if (!initResult.success) {
console.error('Init failed:', initResult.error.message);
return;
}
const container = document.getElementById('ad-container');
const result = await sdk.loadNativeAd({
target: container,
prompt: 'best laptops for programming',
aiResponse: 'Based on your needs, I recommend...'
});
if (result.success) {
const { adData, cleanup } = result.data;
// Render your ad UI inside the target element
container.innerHTML = `<h3>${adData.title}</h3><p>${adData.description}</p>`;
}Or use SDK-rendered templates:
import { NativeAdSize } from '@velocityio/web-sdk';
const result = await sdk.loadNativeAdView({
target: container,
size: NativeAdSize.MEDIUM,
prompt: 'best laptops for programming',
aiResponse: 'Based on your needs, I recommend...'
});Migrating from v0.6.x? See the v0.7.0 migration guide for the consolidated template set, removed mobile variants, changed defaults, and new theming options.
Consent & Privacy
The SDK supports GDPR and CCPA compliance with automatic CMP detection and explicit consent APIs.
Automatic CMP Detection
The SDK automatically reads consent signals from any IAB TCF v2 compatible CMP (OneTrust, Didomi, etc.) via the standard __tcfapi interface. No configuration needed — if a CMP is present on the page, the SDK reads its consent data.
Explicit Consent API
import type { ConsentConfig } from '@velocityio/web-sdk';
// Option 1: Set consent at construction time
const sdk = new VelocitySDK({
publisherKey: 'YOUR_KEY',
consent: {
gdprConsent: true,
ccpaDoNotSell: false
}
});
// Option 2: Set consent dynamically
sdk.setConsent(true); // GDPR consent granted
sdk.setConsent(false); // GDPR consent revoked
sdk.setDoNotSell(true); // CCPA opt-outHow It Works
- The SDK sends consent signals to the server in every init/load request
- If GDPR applies (detected via CMP), the SDK checks TCF Purpose 1 ("Store and/or access information on a device") — data is only stored when Purpose 1 is granted
- Revoking consent (
setConsent(false)) immediately takes effect - If no CMP is present, the SDK falls back to server-side geo detection — if the user is in a GDPR region, data is not stored; otherwise it is
Default Behavior
When neither setConsent() nor setDoNotSell() is called, the SDK relies on CMP signals. If a CMP indicates GDPR applies, Purpose 1 consent is required before data is stored. If no CMP is present, the SDK uses server-side geo detection to determine whether GDPR applies — users in GDPR regions will have data storage withheld until consent is granted.
Embedding the SDK in an iframe
When the SDK runs inside a cross-origin iframe (a widget loaded from your own asset host, for example), the frame's window.location names that host — not the publisher page the user is actually on. Without help, every request would be attributed to the asset host.
The SDK handles this in two ways.
1. Automatic detection (no code changes). The SDK detects it is framed — in any iframe — and recovers the top-level page. In an iframe with the same origin as the top-level page it reads that page's full URL directly. In any other (cross-origin) iframe it falls back to location.ancestorOrigins or document.referrer, which is best-effort: it yields only an origin (never the path), and it can fail entirely when the iframe has referrerpolicy="no-referrer" — Firefox then reports the parent as "null" and sends no referrer, so the SDK falls back to the iframe's own host. Chromium and Safari still expose the parent origin in that case.
2. Explicit override (recommended when you know the page). Pass the publisher's identity and it wins over detection:
const sdk = new VelocitySDK({
publisherKey: 'YOUR_PUBLISHER_KEY',
siteDomain: 'example.com', // hostname only — no scheme, no path
siteUrl: 'https://example.com/news/some-article' // absolute URL of the embedding page
});Prefer siteUrl: it sets the reported page URL, and also the domain when siteDomain is omitted. siteDomain sets only the domain — on its own, the page URL still comes from detection, or from the iframe's own location. Config values cover init() and every load.
new VelocitySDK() throws a ConfigurationError synchronously if siteDomain is empty or contains : or / (no scheme, port or path), or if siteUrl is empty or not an absolute http/https URL.
Per-request override. For SPA routes or infinite scroll where the page changes without a new SDK instance, pass siteUrl on the load call. For that request — the ad request and all of its events, including impressions and clicks — it replaces both configured values (siteUrl and siteDomain), so the reported domain always matches the reported page. An invalid value (not an absolute http/https URL) is ignored — a warning is logged, but production builds stay silent unless you pass a logger — and the configured values apply; the ad still loads.
const result = await sdk.loadNativeAdView({
target: container,
adUnitId: 'YOUR_AD_UNIT_ID',
size: NativeAdSize.MEDIUM,
prompt: 'best laptops for programming',
aiResponse: 'Based on your needs, I recommend...',
siteUrl: hostPageUrl // the route currently being viewed
});Inside a cross-origin iframe the SDK can't read the host page's URL for you — window.top.location.href throws a SecurityError there. Have the host page pass it in: as a parameter on the iframe's src, or via postMessage when the route changes.
Cleanup & Lifecycle
Call destroy() when the SDK instance is no longer needed to release all internal resources:
sdk.destroy();This stops CMP observers, activity listeners, and session tracking. After calling destroy(), the instance cannot be reused — create a new VelocitySDK instance if needed.
When to call destroy():
- SPA route transitions where the SDK is no longer needed
- Component unmount in frameworks like React/Vue/Angular
- Before creating a new SDK instance with different configuration
When you don't need destroy():
- Standard multi-page sites (page unload cleans up automatically)
- Single SDK instance that lives for the entire page session
Attribution / Conversion Tracking
Conversion tracking for advertisers ships as a separate package: @velocityio/web-attribution-sdk.
Documentation
For detailed guides, API reference, examples, and troubleshooting, visit the Velocity documentation.
License
MIT
