Plugins
The Experience SDK uses a plugin architecture powered by @lytics/sdk-kit (opens in a new tab). Plugins extend the runtime with additional capabilities.
Official Plugins
Banner Plugin
Renders banner experiences in the DOM with automatic positioning, theming, and responsive layout.
Configuration
import { createInstance } from '@prosdevlab/experience-sdk';
const experiences = createInstance({
banner: {
position: 'top', // 'top' | 'bottom' (default: 'top')
zIndex: 10000, // Custom z-index (default: 10000)
dismissable: true // Allow dismissal (default: true)
}
});API Methods
banner.show(experience)
Manually show a banner experience.
experiences.banner.show({
id: 'welcome',
type: 'banner',
targeting: {},
content: {
title: 'Welcome!',
message: 'Thanks for visiting.',
buttons: [
{ text: 'Get Started', url: '/start', variant: 'primary' }
]
}
});banner.remove(experienceId)
Remove a specific banner.
experiences.banner.remove('welcome');banner.isShowing(experienceId?)
Check if a banner is currently showing.
// Check specific banner
if (experiences.banner.isShowing('welcome')) {
console.log('Welcome banner is visible');
}
// Check if any banner is showing
if (experiences.banner.isShowing()) {
console.log('A banner is visible');
}Button Variants
Banners support multiple buttons with different visual styles:
buttons: [
{
text: 'Accept all',
action: 'accept',
variant: 'primary', // Blue, prominent
metadata: { consent: ['all'] }
},
{
text: 'Reject',
action: 'reject',
variant: 'secondary', // Gray, outlined
metadata: { consent: [] }
},
{
text: 'Preferences',
action: 'preferences',
variant: 'link', // Text link style
url: '/preferences'
}
]Variants:
primary- Blue button for main actions (default)secondary- Gray outlined button for secondary actionslink- Text link style for tertiary actions
Responsive Layout
Banners automatically adapt to screen size:
- Desktop (>640px): Buttons display inline horizontally
- Mobile (≤640px): Buttons stack vertically for better touch interaction
Events
The banner plugin emits the following events:
experiences:shown
experiences.on('experiences:shown', ({ experienceId, type }) => {
console.log(`${type} shown:`, experienceId);
});experiences:action
experiences.on('experiences:action', ({ experienceId, action, variant, metadata, url }) => {
console.log('Button clicked:', action, 'variant:', variant);
if (metadata) {
console.log('Metadata:', metadata);
}
});experiences:dismissed
experiences.on('experiences:dismissed', ({ experienceId }) => {
console.log('Banner dismissed:', experienceId);
});See Banner Examples for complete usage examples.
Customization
The Experience SDK focuses on targeting logic, not visual design. The banner plugin provides minimal, functional default styles that you can customize using CSS.
CSS Classes
The banner plugin uses the .xp-* namespace for all CSS classes:
.xp-banner- Main container.xp-banner--top- Top positioned banner.xp-banner--bottom- Bottom positioned banner.xp-banner__container- Inner wrapper.xp-banner__content- Content section.xp-banner__title- Optional title.xp-banner__message- Main message text.xp-banner__buttons- Buttons container.xp-banner__button- Individual button.xp-banner__button--primary- Primary button variant.xp-banner__button--secondary- Secondary button variant.xp-banner__button--link- Link button variant.xp-banner__close- Close button
Use Case 1: User with Tailwind
Add Tailwind classes via the className property:
experiences.register('flash-sale', {
type: 'banner',
content: {
message: 'Flash Sale: 50% Off Everything!',
className: 'bg-gradient-to-r from-blue-600 to-purple-600 text-white',
buttons: [{
text: 'Shop Now',
url: '/shop',
variant: 'primary',
className: 'bg-white text-blue-600 hover:bg-gray-100'
}]
},
targeting: { url: { contains: '/shop' } }
});Use Case 2: User with Design System
Build your own plugin using your design system components:
import { MyBannerComponent } from '@your-org/design-system';
const myBannerPlugin: PluginFunction = (plugin, instance, config) => {
instance.on('experiences:evaluated', ({ decision, experience }) => {
if (decision.show && experience.type === 'banner') {
// Render using your React component
ReactDOM.render(
<MyBannerComponent {...experience.content} />,
document.getElementById('banner-root')
);
}
});
};
experiences.use(myBannerPlugin);Use Case 3: User with CSS Framework
Add Bootstrap, Material UI, or other framework classes:
experiences.register('alert', {
type: 'banner',
content: {
message: 'Important notice',
className: 'alert alert-warning',
buttons: [{
text: 'Learn More',
className: 'btn btn-primary'
}]
},
targeting: {}
});Inline Styles
For quick overrides, use the style property:
content: {
message: 'Flash Sale!',
style: {
background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
color: 'white',
padding: '24px'
}
}Frequency Plugin
Manages impression tracking and frequency capping using persistent storage.
Configuration
const experiences = createInstance({
frequency: {
enabled: true, // Enable frequency tracking (default: true)
storage: 'local' // 'local' | 'session' | 'memory' (default: 'local')
}
});Experience-Level Frequency
Define frequency caps per experience:
experiences.register('welcome', {
type: 'banner',
content: { message: 'Welcome!' },
frequency: {
max: 3, // Maximum impressions
per: 'session' // 'session' | 'day' | 'week'
}
});API Methods
frequency.getImpressionCount(experienceId, period?)
Get impression count for an experience.
const count = experiences.frequency.getImpressionCount('welcome', 'session');
console.log(`Shown ${count} times this session`);Parameters:
experienceId: string- Experience to checkperiod?: 'session' | 'day' | 'week'- Time period (optional)
Returns: number
frequency.recordImpression(experienceId)
Manually record an impression.
experiences.frequency.recordImpression('welcome');frequency.reset(experienceId?)
Reset impression counts.
// Reset specific experience
experiences.frequency.reset('welcome');
// Reset all experiences
experiences.frequency.reset();How It Works
- Impressions are recorded when
experiences:shownevent is emitted - Storage persists counts in localStorage (or sessionStorage/memory)
- Evaluation checks counts before showing experiences
- Dismissals do NOT count as impressions
Storage Keys
Frequency data is stored with namespaced keys:
experiences.frequency.session:welcome = 3
experiences.frequency.day:2024-12-25:welcome = 1
experiences.frequency.week:2024-W52:welcome = 5Debug Plugin
Provides console logging and window event emission for debugging and Chrome extension integration.
Configuration
const experiences = createInstance({
debug: {
enabled: true, // Enable debug output (default: false)
windowEvents: true, // Emit to window (default: true when enabled)
prefix: 'experiences' // Log prefix (default: 'experiences')
}
});Or use the shorthand:
const experiences = createInstance({ debug: true });API Methods
debug.log(message, data?)
Log a message with optional data.
experiences.debug.log('User clicked button', { action: 'cta' });Console output:
[experiences] User clicked button { action: 'cta' }Window event:
window.addEventListener('experiences:debug', (event) => {
console.log(event.detail);
// { message: 'User clicked button', data: { action: 'cta' }, timestamp: ... }
});Automatic Logging
When debug mode is enabled, the plugin automatically logs:
- SDK initialization
- Experience registration
- Evaluation results
- Decision reasons
- Event emissions
const experiences = createInstance({ debug: true });
experiences.register('welcome', { ... });
// [experiences] Experience registered: welcome
const decision = experiences.evaluate();
// [experiences] Evaluating 1 experience(s)
// [experiences] Decision: show=true, experience=welcome
// [experiences] Reasons: ["✅ URL matches", "✅ Frequency: 0/3 this session"]Chrome Extension Integration
The debug plugin emits events to window that can be captured by Chrome extensions:
// In Chrome extension content script
window.addEventListener('experiences:debug', (event) => {
chrome.runtime.sendMessage({
type: 'EXPERIENCE_DEBUG',
payload: event.detail
});
});This enables building DevTools panels for inspecting experience decisions in real-time.
Plugin Development
The SDK uses @lytics/sdk-kit (opens in a new tab)'s plugin system. Custom plugins can be created using the PluginFunction interface:
import type { PluginFunction } from '@lytics/sdk-kit';
const myPlugin: PluginFunction = (plugin, instance, config) => {
// Namespace
plugin.ns('my.plugin');
// Default config
plugin.defaults({ myPlugin: { enabled: true } });
// Expose API
plugin.expose({
myMethod() {
console.log('Hello from plugin!');
}
});
// Listen to events
instance.on('experiences:evaluated', (decision) => {
// React to evaluations
});
};
// Use the plugin
const experiences = createInstance();
experiences.use(myPlugin);See the sdk-kit documentation (opens in a new tab) for complete plugin development guide.
Next Steps
- Banner Examples - Complete banner usage examples
- Events Reference - All SDK events
- API Reference - Core API documentation