JavaScript API
The FanID Widget exposes a global FanIDWidget object with methods for gating, authentication, and event handling.
Initialization
FanIDWidget.init(config)
Initialize the widget. Must be called once before using any other methods (except on() — see Events below).
baseUrl is required.
FanIDWidget.init({
baseUrl: 'https://your-org.fanid.co',
floatingWidget: false,
gatedContent: {
style: 'blur',
},
})
FanIDWidget.destroy()
Unmount the widget, remove all gates, and clean up.
FanIDWidget.destroy()
FanIDWidget.isInitialized()
Returns true if the widget has been initialized.
if (FanIDWidget.isInitialized()) {
// Safe to call gating methods
}
Floating Widget
FanIDWidget.showFloatingWidget()
Programmatically show the floating sign-in/profile panel, even if floatingWidget: false or autoShow: false
was set during init. Also clears any persisted "user closed" flag, so the panel becomes visible even when
persistClose: 'persistent' is active.
FanIDWidget.showFloatingWidget()
FanIDWidget.hideFloatingWidget()
Programmatically hide the floating panel at any time. Does not set the persisted close flag — use this for temporary hides. User-initiated close (× button) is what writes to session/localStorage.
FanIDWidget.hideFloatingWidget()
FanIDWidget.setFloatingWidgetPosition(position)
Change the floating panel's position at runtime. Accepts 'top-left', 'top-right', 'bottom-left',
'bottom-right', or 'center'. If the panel is currently mounted, it is remounted with the new position (re-runs
the entrance animation).
FanIDWidget.setFloatingWidgetPosition('bottom-right')
Example: custom sign-in button
FanIDWidget.init({ baseUrl: 'https://your-org.fanid.co', floatingWidget: false })
document.getElementById('my-signin-btn').addEventListener('click', () => {
FanIDWidget.showFloatingWidget()
})
Example: persistent dismiss
// Once user closes, widget stays hidden across reloads until your app re-opens it
FanIDWidget.init({
baseUrl: 'https://your-org.fanid.co',
floatingWidget: { persistClose: 'persistent' },
})
// Your app can bring it back on demand
document.getElementById('signin-link').addEventListener('click', () => {
FanIDWidget.showFloatingWidget()
})
Gated Content
FanIDWidget.gate(target, options?)
Gate a DOM element by CSS selector or reference.
| Parameter | Type | Description |
|---|---|---|
target | string | HTMLElement | CSS selector or DOM element |
options.placeholder | object | { title, message, buttonText } overrides |
options.style | string | 'blur', 'gradient', or 'cover' |
options.blurAmount | number | Blur intensity in pixels |
options.minHeight | number | Minimum height for the gate container |
options.teaserHeight | number | Visible teaser height (gradient mode) |
FanIDWidget.gate('#stats', {
placeholder: { title: 'Premium Stats' },
style: 'gradient',
minHeight: 300,
})
FanIDWidget.ungate(target)
Remove gating from an element.
FanIDWidget.ungate('#stats')
FanIDWidget.element(config)
Gate an element using a config object (alternative to gate()).
FanIDWidget.element({
el: '#premium-section',
placeholder: { title: 'Premium', buttonText: 'Unlock' },
style: 'blur',
})
FanIDWidget.isGated(target)
Check if an element is currently gated. Returns boolean.
FanIDWidget.isGated('#stats') // true | false
FanIDWidget.gateFullPage(options?)
Display a full-viewport gating overlay. See Full-Page Gating.
FanIDWidget.ungateFullPage()
Remove the full-page gating overlay.
Authentication
FanIDWidget.isAuthenticated()
Check if the current user is authenticated. Returns Promise<boolean>.
const loggedIn = await FanIDWidget.isAuthenticated()
FanIDWidget.getProfile()
Get the authenticated user's profile. Returns Promise<SubscriberModel | null>.
The profile object includes:
| Field | Type | Description |
|---|---|---|
firstName | string | User's first name |
lastName | string | User's last name |
email | string | User's email address |
phone | string | null | Phone number |
countryCode | string | Country code |
birthdate | string | null | Date of birth |
active | boolean | Account active status |
const profile = await FanIDWidget.getProfile()
if (profile) {
console.log(`Hello, ${profile.firstName} ${profile.lastName}`)
console.log(`Email: ${profile.email}`)
}
FanIDWidget.getOrganization()
Get the current organization that the widget was initialized against. Returns OrganizationModel | null synchronously — null before the widget has finished initializing or when the organization could not be resolved.
The returned object exposes the tenant's branding (title, subtitle, logo URL, primary/accent colors) and identity (id, name, domainName). Use it to label your own UI (header sign-in CTAs, account menus, etc.) without re-fetching /api/subscriber/organization.
| Field | Type | Description |
|---|---|---|
id | string | Tenant ID |
name | string | Display name (e.g. "FanID") |
domainName | string | Tenant domain (e.g. "demo.fanid.co") |
branding.title | string | null | Brand title (e.g. "Demo FanID") |
branding.subtitle | string | null | Brand subtitle / tagline |
branding.logoUrl | string | null | Logo URL |
branding.primaryColor | string | null | Primary brand color (hex) |
branding.accentColor | string | null | Accent / secondary brand color (hex) |
Gate access on the ready event — the organization is resolved during initialization:
FanIDWidget.on('ready', () => {
const org = FanIDWidget.getOrganization()
const label = org?.branding.title ?? org?.name ?? 'Sign in'
document.getElementById('header-signin-btn').textContent = label
})
FanIDWidget.login()
Redirect the user to the FanID login page. The current page URL is passed as the return URL.
FanIDWidget.login()
FanIDWidget.logout()
Log the user out and re-gate all content. Returns Promise<void>.
await FanIDWidget.logout()
Events
FanIDWidget.on(event, callback)
Subscribe to a widget event. Can be called before init() — event handlers registered early will fire when the
corresponding event occurs after initialization.
// Register before init — will fire when widget is ready
FanIDWidget.on('ready', () => {
console.log('Widget initialized')
})
FanIDWidget.init({ baseUrl: 'https://your-org.fanid.co' })
FanIDWidget.off(event, callback)
Unsubscribe from a widget event. Pass the same function reference used in on().
const handler = (profile) => console.log('Welcome', profile.firstName)
FanIDWidget.on('auth:login', handler)
// Later
FanIDWidget.off('auth:login', handler)
Event reference
| Event | Payload | Description |
|---|---|---|
ready | none | Widget initialization complete |
auth:login | SubscriberModel | User authenticated |
auth:logout | none | User logged out |
gate:applied | HTMLElement | Gating overlay applied to an element |
gate:reveal | HTMLElement | Gated content revealed after authentication |
gate:click | HTMLElement | User clicked the sign-in button on a gate |
Example: custom analytics
FanIDWidget.on('gate:click', (element) => {
analytics.track('fanid_gate_click', {
elementId: element.id,
page: window.location.pathname,
})
})
FanIDWidget.on('auth:login', (profile) => {
analytics.identify(profile.email)
})
Example: reactive UI updates
FanIDWidget.on('auth:login', async () => {
const profile = await FanIDWidget.getProfile()
document.getElementById('user-name').textContent = profile.firstName
document.getElementById('user-email').textContent = profile.email
})
FanIDWidget.on('auth:logout', () => {
document.getElementById('user-name').textContent = ''
document.getElementById('user-email').textContent = ''
})
Auth state on <body>
Whenever the user's auth state changes — on init, after login, after logout, and after a cross-tab session
update — the widget toggles a data-fanid-authed attribute on <body>. Use it to drive CSS-only soft gating
without subscribing to events:
[data-fanid-locked] { display: none; }
body[data-fanid-authed] [data-fanid-locked] { display: block; }
See Soft Gating with CSS for the full pattern.
Cross-tab sync
The widget watches the storage event for changes to its session entry. If the user signs in or out in one tab,
every other tab on the same origin re-checks the session, updates the body attribute, and emits the matching
auth:login or auth:logout event. This is automatic — no API call from your side is required to keep tabs in
sync.
Styling
All gated content CSS properties are configurable via --fanid-gate-* custom properties. See the
complete styling reference for all available variables.
wmt-fanid-protected {
--fanid-gate-panel-bg: #1a1a2e;
--fanid-gate-button-bg: #e94560;
--fanid-gate-title-color: white;
}
TypeScript
When using the npm package, all types are exported:
import type {
BrandingSettingsModel,
FloatingWidgetConfig,
FloatingWidgetPersistClose,
FloatingWidgetPosition,
OrganizationModel,
Transport,
WidgetConfig,
} from '@wmt-fanid/widget'
import type { GatedContentConfig } from '@wmt-fanid/widget/dist/state'
import type { SubscriberModel } from '@wmt-fanid/widget/dist/types'
Transport is the union 'cookie' | 'bearer' and is the type of the optional transport field on WidgetConfig.