Add shoppable video
FastPix Player now supports shoppable video themes, giving you the ability to embed interactive shopping experiences directly inside your videos. Instead of just watching, viewers can click, explore, and even purchase products while engaging with your content.
There are two themes you can choose from, depending on the type of video experience you want to build:
- Shoppable video player - a full-featured player with a product sidebar, catalog browsing, and timeline-aware product activations.
- Shoppable shorts - a lightweight, mobile-first option optimized for single products and social video formats.
Both themes allow you to add clickable products, hotspots, and calls-to-action seamlessly. The main difference lies in how product data is configured and displayed.
Theme behavior
shoppable-video-player
expects product data passed programmatically through theaddShoppableData()
method. Anyproduct-link
attribute you set will be ignored.shoppable-shorts
only uses theproduct-link
attribute. No product data configuration is needed or processed.
Shoppable video player theme
A full, interactive shopping experience with an expandable sidebar and detailed product catalog. This theme is best suited for multi-product or long-form content where viewers can browse items while watching.
Feature | Description |
---|---|
Interactive Product Sidebar | Expandable panel listing products with thumbnails, names, and descriptions. |
Product Hover Overlays | Text overlays appear when hovering over sidebar items, showing extra product info. |
Image Swap on Hover | Swap product images (e.g., different angles or colors) when hovered. |
Clickable Hotspots | Interactive markers on the video timeline that link directly to products. |
Post-Play Product Overlay | Product carousel appears once the video ends, driving continued engagement. |
Auto Open/Close Sidebar | Sidebar can open automatically on play and auto-close after a set duration. |
Product Click Actions | Clicking a product can seek the video to a timestamp or open an external purchase link. |
Time-Based Product Activation | Products activate and deactivate based on video timestamps, highlighting the right item at the right time. |
Use cases
- E-commerce showcases: Display multiple products with detailed info and links.
- Fashion & lifestyle content: Highlight clothing, accessories, or styling products with hover effects.
- Educational content: Reference books, tools, or course material mentioned in video.
- Long-form content: Manage many products across extended timelines with an organized sidebar.
- Product demos: Highlight specific items precisely at the moment they’re being demonstrated.
Shoppable shorts theme
A simplified, call-to-action driven theme for quick, single-product experiences. Designed for mobile-first and social platforms.
Feature | Description |
---|---|
Single External Link Integration | One-click setup — opens a specified URL when the cart button is tapped. |
Cart Button | Prominent “shop” button optimized for mobile UX. |
Mobile-First Design | UI elements tailored for small screens and touch interactions. |
Minimal UI Footprint | Clean, unobtrusive design that keeps focus on the video. |
No Complex Setup | Requires only the product-link attribute, no extra JavaScript. |
Social Media Optimized | Perfect for TikTok, Instagram Reels, and YouTube Shorts. |
Use cases
- Social media shorts: Quick promos across TikTok, Instagram, YouTube Shorts.
- Mobile-first campaigns: Videos consumed primarily on phones.
- Single-product promos: Focused campaigns where one link drives conversions.
- Fast purchase flows: Low-friction buying experiences.
- Simple CTA campaigns: “Tap to shop” videos pointing to a single destination.
- Influencer marketing: Creators linking directly to sponsored products.
Theme comparison
Feature | Shoppable Video Player | Shoppable Shorts |
---|---|---|
Product Catalog | Full sidebar with multiple products | Single external link only |
Configuration | Requires addShoppableData() with product array | Only needs product-link attribute |
Hotspots | Available (timeline markers) | Not available |
Hover Effects | Overlays and image swaps | Not available |
Post-Play Overlay | Carousel shown after video ends | Not available |
Click Actions | Seek video or open link | External URL only |
Best For | Multiple products, rich experiences | Single product, quick CTAs |
Content Length | Long-form video | Short-form video |
Platform | Web applications, detailed showcases | Social media, mobile-first |
Setting up shoppable video player
This theme is the full-featured option, designed for multi-product or catalog-style experiences. It requires a little configuration, but gives you far more control over how products are displayed and how they interact with the video timeline.
1. Basic setup
At the most basic level, you only need to include the FastPix player with the correct theme and a playback ID:
<fastpix-player
theme="shoppable-video-player"
playback-id="your-playback-id">
</fastpix-player>
This creates a player with shoppable capability, but it won’t show any products yet. To make the sidebar and hotspots come alive, you’ll need to pass product data to the player.
2. Add product data
To load product information, use the addShoppableData()
method. This method expects a JSON configuration that defines both sidebar behavior and the product catalog.
const player = document.querySelector('fastpix-player');
const cartData = {
productSidebarConfig: {
startState: "closed", // "closed" or "openOnPlay"
autoClose: 4, // Auto-close after 4 seconds
showPostPlayOverlay: true // Show overlay when video ends
},
products: [
{
id: 1, // Unique product ID
name: "Product Name", // Product display name
thumbnail: "https://example.com/product.jpg", // Product image URL
description: "Product description", // Optional description
startTime: 0, // When product becomes active (seconds)
endTime: 5, // When product becomes inactive (seconds)
// Click action configuration
onProductClick: {
type: "seek", // "seek" or "openLink"
waitTillPause: 6, // Wait 6 seconds then play
params: {
seekTime: 5 // Seek to 5 seconds
}
},
// Hover action configuration
onProductHover: {
type: "overlay", // "overlay" or "swap"
params: {
description: "Product description appears on hover"
}
},
// Hotspot markers (optional)
markers: [
{
x: 175, // X position as percentage (0-100)
y: 60, // Y position as percentage (0-100)
tooltipPosition: "left", // "top", "bottom", "left", "right"
link: "https://store.com/product" // URL when hotspot clicked
}
]
}
]
};
player.addShoppableData(cartData);
With this setup:
- The sidebar starts closed but opens when playback begins.
- Products appear only during the times you specify with startTime and endTime.
- Clicking a product either seeks the video or opens an external link, depending on configuration.
- Hovering over a product reveals extra details or swaps the product image.
- Optional hotspots can be placed directly on the video itself.
Setting up shoppable shorts
This theme is the lightweight option, optimized for single products and mobile-first consumption (e.g., TikTok, Instagram Reels). Unlike shoppable video player, it doesn’t need a product catalog. Instead, it only requires a single link.
Basic setup
Add the FastPix player with the theme set to shoppable-shorts, plus a product-link attribute. When the video plays, a cart button will automatically appear. Tapping it redirects viewers to the specified product link.
<fastpix-player
theme="shoppable-shorts"
product-link="https://your-store.com"
playback-id="your-playback-id">
</fastpix-player>
PLEASE NOTE
For shoppable-shorts, only the
product-link
attribute is required. No additional JavaScript configuration needed.
Summary of setup differences
shoppable-video-player:
- Requires calling
addShoppableData(config)
with a product array. - Supports multiple products, sidebars, overlays, hotspots, and time-based activation.
- Ignores the product-link attribute.
shoppable-shorts:
- Requires only the product-link attribute.
- Supports a single product with a clean “shop” button.
- Ignores product data configuration.
JSON structure explained
The data is structured as a JSON object with two main parts:
productSidebarConfig
- defines how the sidebar behaves (when it opens, closes, and whether overlays appear).products
- an array of product objects, each representing a clickable product inside your video.
Here’s the complete structure:
{
productSidebarConfig: {
startState: "closed", // Sidebar initial state
autoClose: 4, // Auto-close timer (seconds)
showPostPlayOverlay: true // Show overlay when video ends
},
products: [
{
id: 1, // Product ID (number or string)
name: "Product Name", // Product display name
thumbnail: "image-url", // Product image URL
description: "Description", // Optional description
startTime: 0, // Product active start time (seconds)
endTime: 5, // Product active end time (seconds)
onProductClick: { // Click action (optional)
type: "seek", // Action type
waitTillPause: 6, // Wait time before playing
params: { // Action parameters
seekTime: 5 // Target time for seek
}
},
onProductHover: { // Hover action (optional)
type: "overlay", // Action type
params: { // Action parameters
description: "Text to show on hover"
}
},
markers: [ // Hotspot markers (optional)
{
x: 175, // X position (0-100%)
y: 60, // Y position (0-100%)
tooltipPosition: "left", // Tooltip position
link: "url" // Link when clicked
}
]
}
]
}
Product configuration
Products are defined inside the products
array. Each product has required fields (which the player needs to function) and optional fields (to enrich interactivity).
Required fields
Field | Type | Description |
---|---|---|
id | Number / String | Unique product identifier, used internally for tracking and analytics. |
name | String | Product display name, shown in sidebar, tooltips, and overlays. |
thumbnail | String | URL of the product image (appears in sidebar and hover overlays). |
Optional fields
Field | Type | Description |
---|---|---|
description | String | Additional product details shown in overlays and tooltips. |
startTime | Number | Timestamp (in seconds) when product becomes active in the video. |
endTime | Number | Timestamp (in seconds) when product becomes inactive. |
onProductClick | Object | Defines what happens when a product is clicked. |
onProductHover | Object | Defines hover behavior (text overlays or image swaps). |
markers | Array | List of hotspots placed directly on the video (time + position). |
Product actions reference
Products can trigger two types of interactivity:
Click actions
Defines what happens when a product is selected in the sidebar or overlay.
Action Type | Description | Parameters | Default Values |
---|---|---|---|
| Opens an external URL in a new tab. |
|
|
| Seeks the video to a specific timestamp. |
|
Click action configuration example:
// Open external link with video pause
onProductClick: {
type: "openLink",
params: {
targetUrl: "https://store.com/product",
shouldPause: true
}
}
// Seek to specific time with wait
onProductClick: {
type: "seek",
params: {
seekTime: 45,
waitTillPause: 10
}
}
Hover actions
Hover actions control what happens when a user moves their mouse over a product in the sidebar.
Action Type | Description | Parameters | Required |
---|---|---|---|
"overlay" | Shows a text overlay on hover. | description (string) → text to display | Required |
"swap" | Switches product image on hover. | switchImage (string) → alternative image URL | Required |
Hover action configuration example:
// Show text overlay on hover
onProductHover: {
type: "overlay",
params: {
description: "Premium product with excellent quality"
}
}
// Switch image on hover
onProductHover: {
type: "swap",
params: {
switchImage: "https://example.com/product-alt-view.jpg"
}
}
Sidebar configuration
The productSidebarConfig
object customizes how the sidebar behaves during playback.
Property | Type | Description | Default Value | Options |
---|---|---|---|---|
startState | String | Whether sidebar opens automatically when video plays. | "openOnPlay" | "closed" , "openOnPlay" |
autoClose | Number | Auto-close sidebar after X seconds. | undefined | Any positive integer |
showPostPlayOverlay | Boolean | Show product carousel after video ends. | false | true or false |
Example:
productSidebarConfig: {
startState: "openOnPlay", // Sidebar opens when video starts
autoClose: 30, // Auto-close after 30 seconds
showPostPlayOverlay: true // Show overlay when video ends
}
Hotspot marker configuration
Hotspot markers let you place clickable pins directly inside the video frame. These markers can appear at specific times during playback, linking viewers to products or external pages. They’re a powerful way to make your video feel more interactive - imagine a furniture demo where pins appear directly on the chair or table being shown.
Each marker is defined inside the markers
array of a product object.
Marker object structure
Property | Type | Required | Description | Default Value |
---|---|---|---|---|
x | Number | Yes | Horizontal position of the marker, expressed as a percentage of the video width (0–100). | None |
y | Number | Yes | Vertical position of the marker, expressed as a percentage of the video height (0–100). | None |
tooltipPosition | String | Yes | Direction of the tooltip relative to the hotspot. | None |
link | String | Yes | URL to open when the hotspot is clicked. | None |
Example:
markers: [
{
seekTime: 15, // Appear at 15 seconds
x: 25, // 25% from left
y: 30, // 30% from top
tooltipPosition: "bottom", // See below table for tooltip positioning
link: "https://store.com/product"
}
]
In this example:
- A marker appears 15 seconds into the video.
- It’s positioned at 25% from the left and 30% from the top of the player.
- When hovered, the tooltip shows up below the marker.
- Clicking the marker takes the viewer to an external product page.
Tooltip position options
Tooltips help keep the UI intuitive by making it clear what a marker represents without overwhelming the video with too much text.
CSS customization
By default, the shoppable themes follow FastPix’s built-in styles, ensuring the sidebar, buttons, and overlays adapt well across devices. But in most real-world cases, you’ll want the player to match your brand identity.
FastPix Player supports CSS custom properties (variables) that let you tweak the look and feel without digging into the player’s internals.
Available custom properties:
You can apply these variables directly to the <fastpix-player>
element in your stylesheet:
fastpix-player {
--shoppable-sidebar-width: 30%;
--shoppable-sidebar-background-color: rgba(255, 255, 255, 0.75);
--accent-color: #ff6b35;
}
Events
Beyond displaying products, the shoppable player emits events you can listen for in JavaScript. These events allow you to:
- Track user interactions (clicks, hovers, replays).
- Build custom analytics pipelines.
- Trigger custom UI or backend logic based on how viewers interact with products.
Events are emitted both for sidebar interactions and for the post-play overlay. Some events also indicate sidebar state changes and video lifecycle actions (like replay).
Available events:
Event | Description | Event Detail |
---|---|---|
productHover | Triggered when a user hovers over a product in the sidebar. | e.detail.product → object with id, name, thumbnail, etc. |
productClick | Triggered when a user clicks on a product in the sidebar. | e.detail.product |
productBarMax | Fired when the product sidebar is opened/expanded. | No details |
productBarMin | Fired when the product sidebar is closed/minimized. | No details |
productHoverPost | Triggered when hovering over a product in the post-play overlay. | e.detail.product |
productClickPost | Triggered when clicking on a product in the post-play overlay. | e.detail.product |
replay | Fired when the video is replayed/restarted. | No details |
Event usage examples
Listening to product events is straightforward - attach event listeners to the player element:
// Product interaction events (with product data)
player.addEventListener('productHover', (e) => {
console.log('Product hovered:', e.detail.product.name);
// Track analytics: product hover in sidebar
});
player.addEventListener('productClick', (e) => {
console.log('Product clicked:', e.detail.product.id);
// Track analytics: product click in sidebar
});
// Sidebar state events (no event detail)
player.addEventListener('productBarMax', () => {
console.log('Sidebar opened');
// Track analytics: sidebar opened
});
player.addEventListener('productBarMin', () => {
console.log('Sidebar closed');
// Track analytics: sidebar closed
});
// Post-play overlay events (with product data)
player.addEventListener('productHoverPost', (e) => {
console.log('Post-play hover:', e.detail.product.name);
// Track analytics: product hover in post-play overlay
});
player.addEventListener('productClickPost', (e) => {
console.log('Post-play click:', e.detail.product.id);
// Track analytics: product click in post-play overlay
});
// Video replay event (no event detail)
player.addEventListener('replay', () => {
console.log('Video replayed');
// Track analytics: video replay
});
Complete example
Here’s a single snippet that wires up the shoppable player, passes product data, customizes CSS, and listens to events.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/@fastpix/fp-player@latest/dist/player.js"></script>
<title>FastPix Player</title>
<style>
#player-playlist {
--shoppable-sidebar-width: 30%;
}
</style>
</head>
<body>
<h3>FastPix Player - Shoppable player & Navigation Demo</h3>
<fastpix-player id="player-playlist" theme="shoppable-video-player"
playback-id="919ec265-f409-4dd8-ac3d-366181e12e7a" custom-domain="stream.fastpix.app" min-resolution="480p"
max-resolution="720p">
</fastpix-player>
<script>
// Wait until the custom element is defined
customElements.whenDefined('fastpix-player').then(() => {
const player = document.getElementById('player-playlist');
const cartData = {// Instead of cartProducts and productSidebarConfig as separate properties, combine them:
productSidebarConfig: {
startState: "openOnPlay",
autoClose: 4,
showPostPlayOverlay: true,
},
products: [
{
id: 1,
thumbnail:
"https://in.zohocommercecdn.com/product-images/JNW+Shajahan+Sofa+Set+Single+Rosewood+1.jpg/431189000086560983/600x600?storefront_domain=www.jfa.in",
name: "chair",
description: "Description 1",
startTime: 0,
endTime: 5,
markers: [
{
x: 175,
y: 60,
tooltipPosition: "left",
link: "https://www.jfa.in/products/JNW-Shajahan-Sofa-Set-Single-Rosewood-Dx-Premium-Wooden-Sofa-Set/431189000029424510",
},
],
onProductClick: {
type: "seek",
waitTillPause: 6,
params: {
seekTime: 5,
},
},
onProductHover: {
type: "overlay",
params: {
description: "see this product in the video",
},
},
},
{
id: 2,
thumbnail:
"https://in.zohocommercecdn.com/product-images/FDI+Treviso+Sofa+3+Seater+1.jpg/431189000087278412/600x600?storefront_domain=www.jfa.in",
name: "Treviso Sofa",
description: "Description 1",
startTime: 6,
endTime: 10,
markers: [
{
x: 60,
y: 50,
tooltipPosition: "left",
link: "https://www.jfa.in/products/aa55d60413/431189000071080281",
},
],
onProductClick: {
type: "seek",
waitTillPause: 3,
params: {
seekTime: 7,
},
},
onProductHover: {
type: "overlay",
params: {
description: "see this product in the video",
},
},
},
{
id: 3,
thumbnail:
"https://in.zohocommercecdn.com/product-images/1400x1400-Photoroom+%281%29.jpg/431189000076435150/600x600?storefront_domain=www.jfa.in",
name: "Product 2",
description: "Description 2",
startTime: 11,
endTime: 18,
onProductClick: {
type: "openLink",
shouldPause: true,
params: {
targetUrl:
"https://www.jfa.in/products/guru-ct-01-computer-table-30x18x30-walnut-computer-study-table/431189000070278273",
},
},
onProductHover: {
type: "overlay",
params: {
description: "Click to view the product",
},
},
},
{
id: 4,
thumbnail:
"https://in.zohocommercecdn.com/product-images/AMM+Topaz+Plastic+Chair+W+Metal+Leg+and+Seat+Cushion+YellowOffice+Chair+3.jpg/431189000087691668/300x300?storefront_domain=www.jfa.in",
name: "AMM Topaz Plastic Chair",
description: "Description 3",
markers: [
{
x: 50,
y: 50,
tooltipPosition: "top",
link: "https://www.jfa.in/products/JNW-DT-Heart-Jali-Dining-Table-60X36-Walnut-Dining-Table/431189000029421080",
},
],
onProductClick: {
type: "seek",
waitTillPause: 30,
params: {
seekTime: 32,
},
},
onProductHover: {
type: "swap",
params: {
switchImage:
"https://in.zohocommercecdn.com/product-images/AMM+Topaz+Plastic+Chair+W+Metal+Leg+and+Seat+Cushion+YellowOffice+Chair+1.jpg/431189000087691662/600x600?storefront_domain=www.jfa.in",
},
},
},
],
};
// Provide your shoppable JSON
player.addShoppableData(cartData);
// Optional: listen to events
player.addEventListener('productHover', (e) => console.log('hover:', e.detail.product));
player.addEventListener('productClick', (e) => console.log('click:', e.detail.product));
player.addEventListener('productBarMax', () => console.log('bar opened'));
player.addEventListener('productBarMin', () => console.log('bar closed'));
player.addEventListener('productHoverPost', (e) => console.log('overlay hover:', e.detail.product));
player.addEventListener('productClickPost', (e) => console.log('overlay click:', e.detail.product));
player.addEventListener('replay', () => console.log('replay'));
});
</script>
</body>
</html>
PLEASE NOTE
In examples elsewhere you may see
markers
includeseekTime
. If present, it controls when a marker appears. If omitted, the marker’s visibility can be inferred from the product’sstartTime
/endTime
. Your implementation can support either pattern, but keep it consistent within your project.If both
markers
andonProductClick
are used,onProductClick
takes precedence.FastPix Player automatically handles responsiveness.
Troubleshooting
Cart Button Not Displaying
If the cart button isn’t appearing, check these common issues:
- Theme not set correctly
<!-- CORRECT -->
<fastpix-player theme="shoppable-video-player" ...>
<!-- INCORRECT -->
<fastpix-player theme="default" ...>
- Player not initialized
Make sure the player is fully loaded before adding shoppable data:
// Wait for player to be ready
customElements.whenDefined('fastpix-player').then(() => {
const player = document.getElementById('my-player');
// Wait for player to be fully initialized
player.addEventListener('loadedmetadata', () => {
// Now add shoppable data
player.addShoppableData(cartData);
});
});
- Missing product data
For shoppable-video-player, you must call addShoppableData()
:
// REQUIRED for shoppable-video-player
player.addShoppableData({
productSidebarConfig: { ... },
products: [ ... ]
})
Note: The product-link attribute is ignored for shoppable-video-player theme. Only shoppable-shorts theme uses the product-link attribute.
- CSS Conflicts
Ensure no CSS is hiding the cart button:
/* Check if cart button is hidden */
.cartButton {
display: none; /* This would hide the button */
}
/* Check for other potential conflicts */
.cartButton {
visibility: hidden; /* This would hide the button */
opacity: 0; /* This would make the button invisible */
z-index: -1; /* This would put the button behind other elements */
}
/* Check for responsive hiding */
@media (max-width: 150px) {
.cartButton {
display: none; /* This hides cart button on very small screens */
}
}
Common CSS issues:
- CSS Variable syntax: Ensure CSS variables use double dashes (e.g., --shoppable-sidebar-width, not -shoppable-sidebar-width)
- Theme-specific behavior: shoppable-shorts cart button is always visible regardless of screen size
- Force show cart button (Debug)
If the cart button still doesn't appear, you can force it to show:
// Debug method to force show cart button
const player = document.getElementById('my-player');
player.showCartButton();
// For shoppable-shorts specifically
if (player.getAttribute('theme') === 'shoppable-shorts') {
player.ensureShoppableShortsCartButton();
}
Debug steps
- Check console: Look for JavaScript errors
- Verify theme: Ensure
theme="shoppable-video-player"
ortheme="shoppable-shorts"
is set. When using shoppable-video-player, the correct method to pass configuration must be usedplayer.addShoppableData(cartData);
- Check network: Ensure
player.js
is loading correctly (no 404/CORS). - Inspect element: Check if cart button exists in DOM but is hidden
Updated about 11 hours ago