Embed the Genuin Web SDK on your digital properties
Render your brand, community, and group feeds on your digital properties with Web SDK 2.0.6: desktop and mobile web, app web views, CTV and OTT apps, and DOOH screens.
The Genuin Web SDK is a script that turns a <div> on a web page into a video embed. That page can run on any of your digital properties: a website on desktop or mobile, a web view in your app, an HTML5 app on a connected TV, or a player on a digital out-of-home (DOOH) screen. You configure the embed in your Business Account, which feed it shows and how it's laid out, and the SDK fetches that configuration by its embed ID and renders it. Saving a change in your Business Account updates every page and screen that shows the embed at its next load.
This page covers embeds, where you pick the feed once. A placement chooses its videos at load time from the page a visitor is on; see Add a Genuin placement to your digital properties. Both use the same script and the same init call.
Where the Web SDK runs
The Web SDK runs on any screen that renders a web page with a current web engine. That covers these digital properties:
| Digital property | Where the SDK runs | Examples | Setup |
|---|---|---|---|
| Desktop web | Desktop browsers | Article and product pages, homepages, community hubs | Desktop and mobile web |
| Mobile web | Browsers on phones and tablets | The same pages on a phone, with a full-width carousel or a full-screen feed | Desktop and mobile web |
| Mobile apps | A web view inside your iOS or Android app. Native app screens use the iOS, Android, React Native, or Flutter SDK instead. | Hybrid apps, in-app article readers, app screens built as web pages | Mobile app web views |
| CTV and OTT apps | HTML5 apps on smart TVs and streaming devices: Samsung (Tizen) and LG (webOS) TV apps, and Android TV, Google TV, or Fire TV apps that show a web view | A row of short videos on your streaming app's home screen, clips about the show on its details screen | CTV and OTT apps |
| FAST channels | The HTML5 app around the channel's stream, such as your channel's own CTV app. The SDK doesn't run inside the linear stream. | Clips about what's on now, on the channel app's home or details screen | FAST channels |
| DOOH screens | Digital signage players, kiosks, and venue screens that render HTML5 pages | Retail displays, lobby and venue screens, touchscreen kiosks | DOOH screens |
Roku and Apple TV apps can't load web pages, so the Web SDK doesn't run there, and Genuin has no TV SDK for those platforms.
What the SDK renders
An embed combines a feed source with a style, both set in your Business Account under Grow > On Site > Embed.
| Part | Choices | What visitors see |
|---|---|---|
| Feed source | Brand Feed, Community Feed, Group Feed | Everything published across your brand, or the communities or groups you pick |
| Style | Standard Wall, Feed, Carousel | A grid of video tiles with navigation arrows, a vertical feed with a headline and button, or a horizontal row to swipe through |
| Expand view | On or off per embed | Tapping a tile opens the full-screen player with comments, reactions, and sharing over your page |
The SDK renders inside a Shadow DOM, so its styles never leak into your page and your CSS never reaches the player. It shows a skeleton at once, loads the player when the container comes within 200 px of the viewport, and sets the container's height to fit the content.
Requirements
| Requirement | Detail |
|---|---|
| Browser or web engine | ES2020 JavaScript with dynamic import(), Shadow DOM, and IntersectionObserver. Genuin tests Chrome 80, Firefox 75, Safari 13, and Edge 80 and later. On a TV, streaming device, web view, or signage player, the web engine needs the same features, such as Chromium 80 or later; older TV models ship older engines. |
| Video | The device must decode H.264 video. Genuin streams video as HLS with an MP4 fallback, both in H.264. |
| HTTPS | Every SDK asset and API endpoint is served over HTTPS only. Serve the host page over HTTPS as well. |
| Content Security Policy | If your page sets one, allow script-src and style-src for https://media.begenuin.com, connect-src for https://api.begenuin.com, https://media.begenuin.com, and https://rudderstack.begenuin.com, img-src and media-src for https://media.begenuin.com, style-src for https://fonts.googleapis.com, font-src for https://fonts.gstatic.com, and script-src for https://cdn.rudderlabs.com and https://cdn.jsdelivr.net. Brands that run ads add their ad vendors' hosts. |
| Container | A block element with a non-zero width and height. The SDK treats a container with zero width or height as a hidden expand-only host and renders nothing inline. |
| Credentials | An embed ID and your brand's API key, both from your Business Account. The key is a browser key and ships in your page source. |
| One brand per page | Every container on a page must use embeds of the same brand. Sign-in uses the first embed's brand for the whole page. |
Step 1: Copy the embed ID and API key
- In your Business Account, go to Grow > On Site and click Embed.
- On the embed's card, click the ⋯ menu and choose Copy Embed ID.
- Open the embed and click View Embed Code. The Web tab shows your API key in the generated
initcall. Copy the key from there.
To create the embed first, see Embed your social experience on your website.
Step 2: Add the container and the script
Add a container where the embed goes, then load the SDK from the versioned URL. The container needs an id of gen-sdk, an id that starts with gen-sdk-, or the class gen-sdk-class.
<div id="gen-sdk" class="gen-sdk-class" style="width: 100%; height: 600px;"></div>
<script src="https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js"></script>The script is a 6 KB loader. It imports the SDK bundle and its stylesheet from the same /sdk/2.0.6/ directory and queues any init call you make before the bundle arrives.
Caution: Pin the version in the URL. The unversioned https://media.begenuin.com/sdk/gen_sdk.min.js serves the 1.2 line, which has a different API, and a floating URL changes behaviour without a deploy on your side.
Step 3: Initialize the embed
Call window.genuin.init once, after the script tag. You can call it before the bundle has loaded; the loader runs it when ready.
<script>
window.genuin.init({
embed_id: "{{EMBED_ID}}",
api_key: "<<YOUR_API_KEY>>",
});
</script>The SDK finds every container on the page, fetches your brand with the API key, fetches the embed, and renders it. A container's data-* attributes override the matching init value, which is how one init call serves several embeds.
Note: init scans the DOM when it runs. In a framework, call it after the container has rendered; the SDK skips containers it has already initialized, so calling it again is safe.
Step 4: Show several embeds on one page
Give each container a unique id, put its embed ID on the element, and call init once. api_key in init is the fallback for containers without their own data-api-key.
<div id="gen-sdk-1" class="gen-sdk-class" data-embed-id="{{EMBED_ID_1}}"
style="width: 100%; height: 600px;"></div>
<div id="gen-sdk-2" class="gen-sdk-class" data-embed-id="{{EMBED_ID_2}}"
style="width: 100%; height: 400px;"></div>
<script src="https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js"></script>
<script>
window.genuin.init({ api_key: "<<YOUR_API_KEY>>" });
</script>Two containers with the same id log [Genuin SDK Warning]: Found 2 elements with the same ID and only the first initializes.
Step 5: Sign viewers in (Optional)
Visitors can watch without an account. To let them react, comment, and follow as themselves, pass an auto-login token that your server issued for the signed-in user. The SDK exchanges it for a Genuin session, creating the account on first use from params.
window.genuin.init({
embed_id: "{{EMBED_ID}}",
api_key: "<<YOUR_API_KEY>>",
token: "{{AUTO_LOGIN_TOKEN}}",
params: { name: "Ada Lovelace", email: "ada@example.com", nickname: "ada" },
});When the visitor signs in later, call update with the token; it signs them into every embed on the page. Call logout when they sign out of your site.
window.genuin.update({ container_id: "gen-sdk", token: "{{AUTO_LOGIN_TOKEN}}", user_params: {} });
window.genuin.logout();To run your own login screen when a signed-out visitor taps an action, define window.genuinAuth before init. The SDK calls it instead of showing its own sign-in, with the action the visitor attempted and returnQueryParams to restore it after login.
window.genuinAuth = ({ action, returnQueryParams }) => {
// Open your login flow, then hand the token to the SDK:
// window.genuin.update({ container_id: "gen-sdk", token: "{{AUTO_LOGIN_TOKEN}}", user_params: {} });
};An invalid or expired token leaves the visitor signed out; the SDK logs a warning and renders the embed anyway. How tokens are issued is covered in How Auto Login works and Choose how members sign in to the Genuin SDK.
Step 6: Pass page context (Optional)
An embed with no fixed community or group ranks its videos toward the page_context you send. Pass it in contextual_params, and change it with update when a single-page app changes route; the embed reloads with the merged context.
window.genuin.init({
embed_id: "{{EMBED_ID}}",
api_key: "<<YOUR_API_KEY>>",
contextual_params: {
page_context: "electric SUVs, charging, range",
geo: { lat: 37.7749, long: -122.4194 },
},
});
// Later, on a route change:
window.genuin.update({ container_id: "gen-sdk", contextual_params: { page_context: "hybrid sedans" } });On a container, the same values are data-page-context, data-lat, and data-long. The full list of signals and how they rank the feed are in Deliver contextual feeds with page, user, and location context and How contextual feeds choose videos.
Step 7: Open a specific video (Optional)
To land a visitor on one video, pass its slug. By default this opens the expand view on load; set data-expand-on-load="false" to play it inline instead.
<div id="gen-sdk" class="gen-sdk-class"
data-embed-id="{{EMBED_ID}}" data-api-key="<<YOUR_API_KEY>>"
data-start-video-slug="{{VIDEO_SLUG}}"
style="width: 100%; height: 600px;"></div>Add data-action="comment" to open the comment box as well, or data-comment-id to focus one comment. From code, window.genuin.expand("gen-sdk") and window.genuin.collapse("gen-sdk") open and close the expand view of a container.
Set up each digital property
Steps 1 to 7 are the same on every digital property. What changes is the size you give the container, how viewers interact with the screen, and a few settings on the device.
Desktop and mobile web
Give the container a size that suits each screen width. A carousel or grid works as a strip inside your content. A feed or standard wall fills its container, so on a phone give it most of the screen height.
<div id="gen-sdk" class="gen-sdk-class genuin-box"
data-embed-id="{{EMBED_ID}}" data-api-key="<<YOUR_API_KEY>>"></div>
<style>
/* Phones and tablets: full width, most of the screen height */
.genuin-box { width: 100%; height: 80vh; }
/* Desktop: a fixed box beside your content */
@media (min-width: 1024px) { .genuin-box { width: 720px; height: 480px; } }
</style>Mobile app web views
For screens you build natively, use the iOS, Android, React Native, or Flutter SDK. If a screen in your app is a web page, such as a hybrid app or an in-app article reader, the Web SDK runs in its web view the same way it runs in a browser. Set the web view up for inline video and storage:
| Platform | Setting | Why |
|---|---|---|
| iOS (WKWebView) | allowsInlineMediaPlayback = true on the WKWebViewConfiguration | Without it, videos open in the system's full-screen player instead of playing in the embed. |
| iOS (WKWebView) | mediaTypesRequiringUserActionForPlayback = [] | Lets videos autoplay. |
| Android (WebView) | javaScriptEnabled and domStorageEnabled set to true on the WebView's settings | The SDK needs JavaScript, and keeps the viewer's session in local storage. |
| Android (WebView) | mediaPlaybackRequiresUserGesture set to false | Lets videos autoplay. |
To sign members in as your app's signed-in user, pass an auto-login token as in Step 5.
CTV and OTT apps
Samsung (Tizen) and LG (webOS) TVs run apps built as web pages, and Android TV, Google TV, and Fire TV apps can show a web page in a web view. Load the SDK in that page as in Steps 2 and 3. Viewers watch from across the room with a remote, so set the experience up to play without input:
- Fill the screen inside a safe area: give the container about 90% of the screen's width and height, because some TVs crop the edges.
- Match the screen's shape: pick a 16:9 video aspect ratio for the embed or placement in your Business Account.
- Play on its own: on a placement's Configure View tab, under Media Play, turn on Autoplay Video and set Auto-Advance Playback, so the next video starts without a click.
- Plan for the remote: the SDK has no focus navigation for TV remotes, and comments, reactions, and sign-in expect touch, a mouse, or a keyboard. Treat the experience as lean-back, and handle remote keys in your app.
- Test on the device: TV web engines differ by maker and model year. Check the engine against the Requirements above.
<div id="gen-sdk" class="gen-sdk-class tv-screen"
data-placement-id="{{PLACEMENT_ID}}" data-style-id="{{STYLE_ID}}"
data-page-context="weeknight recipes, cooking shows"></div>
<style>
html, body { margin: 0; background: #000; }
/* 1920×1080 and 3840×2160 screens: fill the screen inside a 5% safe area */
.tv-screen { width: 90vw; height: 90vh; margin: 5vh 5vw; }
</style>
<script src="https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js"></script>
<script>
window.genuin.init({ api_key: "<<YOUR_API_KEY>>", theme: "dark" });
</script>Set data-page-context to the show or channel on screen, so the placement ranks videos about it. Change it with update when the viewer moves to another show.
FAST channels
A FAST channel plays one linear video stream that a server assembles, so there's no web page inside the stream for the SDK to run in. Where your channel has its own app, the SDK runs on that app's screens around the stream, set up as described in CTV and OTT apps: for example, clips about what's on now on the home or details screen, with the show's title as page_context. The SDK can't place video inside the stream itself.
DOOH screens
Digital signage players, kiosks, and venue screens that render HTML5 pages run the SDK the same way a browser does. Most of these screens have nobody at the controls, so set the experience up to run on its own:
- Fill the screen: size the container to the screen with 100vw and 100vh. Portrait screens such as 1080×1920 suit the default 9:16 videos; landscape screens suit 16:9.
- Play on its own: on the placement's Configure View tab, under Media Play, turn on Autoplay Video and set Auto-Advance Playback to 3s, 5s, 7s, or Full Video. A grid cycles back to its first video, so it suits a screen that runs all day.
- Show what a passer-by can read: on the same tab, keep components such as the title and leave out buttons, unless the screen is a touchscreen kiosk.
- Don't sign anyone in: a public screen has no signed-in viewer, so pass no
token. - Match the venue: set
data-page-contextto what the location offers, such as the products on the shelves nearby.
<div id="gen-sdk" class="gen-sdk-class signage"
data-placement-id="{{PLACEMENT_ID}}" data-style-id="{{STYLE_ID}}"
data-page-context="running shoes, trail running"></div>
<style>
html, body { margin: 0; overflow: hidden; background: #000; }
/* A portrait screen, 1080×1920: the experience fills it */
.signage { width: 100vw; height: 100vh; }
</style>
<script src="https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js"></script>
<script>
window.genuin.init({ api_key: "<<YOUR_API_KEY>>" });
</script>Use the SDK in a framework
The SDK has no npm package; every framework loads the same script. The pattern is the same everywhere: render the container, load the script once, and call init after it loads.
React
Add a type declaration once so window.genuin compiles.
interface Window {
genuin?: {
init: (config: Record<string, unknown>) => Promise<void>;
update: (config: Record<string, unknown>) => Promise<void>;
on: (event: string, listener: (e: { type: string; payload: unknown }) => void) => Promise<() => void>;
logout: () => Promise<void>;
};
}Then load the script in an effect. The guard keeps React strict mode and re-mounts from adding it twice.
import { useEffect } from "react";
const SDK_URL = "https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js";
export function GenuinEmbed({ embedId }: { embedId: string }) {
useEffect(() => {
if (document.querySelector(`script[src="${SDK_URL}"]`)) {
window.genuin?.init({});
return;
}
const script = document.createElement("script");
script.src = SDK_URL;
script.async = true;
script.onload = () => window.genuin?.init({});
document.body.appendChild(script);
}, []);
return (
<div id="gen-sdk" className="gen-sdk-class" data-embed-id={embedId}
data-api-key="<<YOUR_API_KEY>>" style={{ width: "100%", height: 600 }} />
);
}Next.js
In the App Router, render the container and the script from a client component with next/script. afterInteractive loads the SDK after hydration, and onLoad runs init once the loader is on the page.
"use client";
import Script from "next/script";
export function GenuinEmbed({ embedId }: { embedId: string }) {
return (
<>
<div id="gen-sdk" className="gen-sdk-class" data-embed-id={embedId}
data-api-key="<<YOUR_API_KEY>>" style={{ width: "100%", height: 600 }} />
<Script
src="https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js"
strategy="afterInteractive"
onLoad={() => window.genuin?.init({})}
/>
</>
);
}next/script loads a given src once per session, so onLoad doesn't fire again on client-side navigation. On pages reached that way, call window.genuin?.init({}) from a useEffect as well; already-initialized containers are skipped.
Angular
Inject the script in ngAfterViewInit, once the container exists. The component below is standalone and works in Angular 16 and later.
import { AfterViewInit, Component, Input } from "@angular/core";
@Component({
selector: "genuin-embed",
standalone: true,
template: `<div id="gen-sdk" class="gen-sdk-class" [attr.data-embed-id]="embedId"
data-api-key="<<YOUR_API_KEY>>" style="width: 100%; height: 600px"></div>`,
})
export class GenuinEmbedComponent implements AfterViewInit {
@Input({ required: true }) embedId!: string;
ngAfterViewInit(): void {
const src = "https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.js";
const genuin = () => (window as any).genuin;
if (document.querySelector(`script[src="${src}"]`)) { genuin()?.init({}); return; }
const script = document.createElement("script");
script.src = src;
script.async = true;
script.onload = () => genuin()?.init({});
document.body.appendChild(script);
}
}Configuration reference
init options
Pass these to window.genuin.init. Where a data attribute exists, setting it on a container overrides the init value for that container.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| api_key | string | Yes | none | Your brand's API key. Data attribute: data-api-key. |
| embed_id | string | Yes, unless a placement is set | none | The embed to render. Data attribute: data-embed-id. |
| placement_id | string | No | none | With style_id, renders a placement instead of an embed. See Add a Genuin placement to your digital properties. Data attribute: data-placement-id. |
| style_id | string | No | none | The placement style. Data attribute: data-style-id. |
| token | string | No | none | Auto-login token for the current visitor. Empty, "null", and "undefined" are ignored. Data attribute: data-token. |
| params | object | No | none | Profile for a new account created from token: name, email, mobile, nickname, profileImage (URL), brandUserIdentity. |
| contextual_params | object | No | none | Page and viewer context: page_context, previous_page_context, user_context, url, geo (lat, long, radius_limit), place, time, user_segments, user_interests, brands_ids, community_ids, loop_ids, posted_by_user_ids. Data attributes: data-page-context, data-previous-page-context, data-user-context, data-url, data-lat, data-long, data-geo, data-place, data-time, data-user-segments, data-user-interests, data-brands-ids, data-community-ids, data-loop-ids, data-posted-by-user-ids; objects and arrays as JSON strings. |
| configuration | object | No | none | Placement only. Overrides the style's style_title, style_subtitle, and sections. |
| start_video_slug | string | No | none | Video to open on load. Sets expand_on_load to true unless you set it to false. Data attribute: data-start-video-slug. |
| action | string | No | none | Interaction to perform on the start video: spark, comment-spark, repost, comment, report, join-community, join-group, subscribe-group, become-a-creator, octo. Data attribute: data-action. |
| comment_id | string | No | none | Comment to focus when the start video opens. Data attribute: data-comment-id. |
| auth_info | object | No | none | signInUrl and signUpUrl, each a string or a function returning one. Sign-in prompts send the visitor there instead of showing the SDK's own flow. |
| error_handler | function | No | none | Called with { isError, isNoContent } when an embed fails to load or its feed is empty. |
| theme | "light" or "dark" | No | "light" | Colour theme of the player. Data attribute: data-theme. |
| useShadowDOM | boolean | No | true | Set false to render into the page's DOM; the SDK's styles then share your cascade. |
| allow_gesture_scroll | boolean | No | true | Set false to turn off swipe and drag between tiles. Data attribute: data-allow-gesture-scroll. |
| video_ids | string | No | none | Comma-separated video ids that replace the feed. Data attribute: data-video-ids. |
| initial_video_ids | string | No | none | Comma-separated video ids to show first, ahead of the feed. Data attribute: data-initial-video-ids. |
| targeting | object | No | none | Ad and sponsorship targeting: keywords (string or array), location, page_url, and an open key_value map of up to 50 entries. Keywords and location are read from the page's <meta name="keywords"> and geo-IP when omitted. |
| sponsorship_id | string[] | No | none | Overrides the sponsorship attached to the embed. An empty array counts as absent. |
| expand_on_load | boolean | No | false | Data attribute only: data-expand-on-load="true" opens the expand view as soon as the embed loads. |
| embed_style | "expand_only" | No | none | Data attribute only: data-embed-style="expand_only" renders no inline player and serves the expand view alone. |
| brand_context, website_type, parent_instance_id, live | — | No | none | Partner and internal options for publisher integrations, preview mode, and nested SDK instances. Don't set them unless Genuin asks you to. |
contextualParams, authInfo, and errorHandler still work as aliases but are deprecated; use the snake-case names.
update options
Pass these to window.genuin.update after init. Calls made before the SDK is ready are queued.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| container_id | string | Yes | none | The id of the container to update. |
| token | string | No | none | Signs the visitor into every embed on the page. The TypeScript type lists it as required; an empty string is ignored. |
| user_params | object | No | none | Same keys as params. Listed as required by the type; pass {} when you have nothing to send. |
| contextual_params | object | No | none | Merged into the container's current context, then the feed reloads. |
| targeting | object | No | none | Replaces the container's targeting, so a field you leave out is cleared. |
| start_video_slug | string | No | none | Opens this video in the container's expand view. action and comment_id apply as in init. |
Methods
| Method | Returns | What it does |
|---|---|---|
| init(config) | Promise | Finds containers and renders them. Safe to call before the bundle has loaded. |
| update(config) | Promise | Changes a container's token, context, targeting, or start video. |
| on(event, listener) | Promise of an unsubscribe function | Subscribes to one of the events below. The listener receives { type, payload, timestamp }. |
| off(event, listener) | Promise | Removes a listener. |
| emit(event, payload) | Promise | Sends a command to the player: player:play, player:pause, player:mute, player:unmute, or sdk:themeChange. |
| expand(containerId) | Promise | Opens the container's expand view. |
| collapse(containerId) | Promise | Closes it. |
| logout() | Promise | Clears the signed-in visitor from every embed. |
| destroy() | void | Unmounts every embed and removes all listeners. Available once the bundle has loaded. |
| version, isLoaded(), isLoading() | string, boolean | The loader's version and bundle state. |
Events
Subscribe with on, which returns a function that unsubscribes. off(eventType, listener) removes a listener you kept a reference to. Names outside this list are rejected with a console warning.
window.genuin.on("onPlay", (event) => {
console.log(event.type, event.payload.muted, event.payload.isInView);
});| Event | Payload | Fires when |
|---|---|---|
| onFeedLoaded | videoCount, hasNextPage, isSectioned, feedType, thumbnailUrl, videoUrl | A feed page has loaded |
| onPlay | muted, isInView, isFocused, volume, autoplay | A video starts playing |
| onPause | muted, isInView, isFocused, volume | A video pauses |
| onMuteChange | muted, volume, instanceId | The visitor mutes or unmutes |
| onSwipedForward, onSwipedBackward | fromIndex, toIndex, timestamp | The visitor moves to another video |
| onVideoClicked | videoId | A tile is clicked |
| onExpandViewChanged | true or false | The expand view opens or closes |
| onShare | shareUrl, type, id, clipTitle, clipDescription, clipThumbnailUrl | The visitor shares a video |
| onVideoNotFound | slug, errorCode | A start_video_slug doesn't resolve |
| onAnalyticsTrack | eventName, eventPayload | The SDK records an analytics event, for forwarding to your own analytics |
| onFollowChanged, onCaughtOverlay, checkFollowingStatus, playIHeartContent | varies | Publisher-partner integrations; unused in a standard embed |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Nothing renders; the console shows Failed to fetch brand details | The API key is missing or wrong, or belongs to another environment | Copy the key from the Web tab of View Embed Code and pass it as api_key or data-api-key. |
| Console error Placement ID or Style ID is missing, and no embed ID provided | The container has no data-embed-id and init has no embed_id, or only one of placement_id and style_id was set | Add the embed ID, or both placement values. |
| [Genuin SDK Warning]: Found N elements with the same ID | Two containers share an id | Give each container a unique id, such as gen-sdk-1 and gen-sdk-2. |
| No valid SDK elements found for initialization. | init ran before the container existed, or the container lacks the gen-sdk id prefix and class | Render the container first, then call init. |
| window.genuin is undefined | The init script runs before the SDK script tag, or the script failed to load | Place the script tag before the init call and check the URL in the Network tab. |
| The player shows Unable to load content | The embed doesn't exist, the brand's web SDK is off, or a network error occurred | Check the embed ID in your Business Account and the failing request in the Network tab; error_handler receives isError: true. |
| The expand view opens but nothing renders inline | The container had zero width or height when init ran | Give the container a width and a height in CSS. |
| The visitor stays signed out after passing token | The auto-login request returned 401, or browser storage is blocked | Check that the token is current and issued for this brand. In a private window or inside a third-party iframe, the SDK keeps the session in memory only, so it ends with the page. |
| Scripts, styles, or requests are blocked | Your Content Security Policy doesn't allow a Genuin host | Add the hosts from the Requirements table. |
| SDK initialization is disabled via URL parameter. | The page URL contains disableGenSdk=true | Remove the parameter. |
| Tiles show on a TV or signage player, but videos don't play | The device's web engine is older than the Requirements, or it can't decode H.264 | Check the engine version and H.264 support on the device, and test there before rollout. |
Limitations
- CDN only: There's no npm package. Load
https://media.begenuin.com/sdk/2.0.6/gen_sdk.min.jsand pin the version. - One brand per page: Sign-in resolves the brand from the first embed, so mixing brands on a page breaks authentication.
- Containers need a size: A zero-sized or hidden container is treated as an expand-only host.
- Shadow DOM: Your CSS doesn't style the player, and the player uses the Inter font loaded from Google Fonts. There's no font option in 2.0.6.
- Fixed event list:
onaccepts only the events listed above. Container resizing is handled internally and isn't subscribable. - Context merges, targeting replaces:
updatemergescontextual_paramsinto the existing context but replacestargetingwholesale. - Key-value targeting caps: 50 entries, keys up to 128 characters, values up to 1,024 characters, keywords up to 100 of 256 characters each,
page_urlup to 2,048 characters. Larger values are dropped with a console warning. - Lazy rendering: Embeds render when they come within 200 px of the viewport, except when a start video or expand-on-load is set.
- Web runtimes only: The SDK runs where a web page runs. Roku and Apple TV apps can't load web pages, and a FAST channel's linear stream has no page inside it, so the SDK runs in the app around the stream.
- No TV remote navigation: The SDK doesn't move focus with a remote's arrow keys. On TVs, use autoplay with auto-advance and handle remote keys in your app.

