惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
量子位
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
IT之家
IT之家
F
Fortinet All Blogs
GbyAI
GbyAI
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Register - Security
The Register - Security
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
A
Arctic Wolf
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
Recent Announcements
Recent Announcements
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Blog — PlanetScale
Blog — PlanetScale
L
LangChain Blog
P
Palo Alto Networks Blog
Y
Y Combinator Blog
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AWS News Blog
AWS News Blog
有赞技术团队
有赞技术团队
Engineering at Meta
Engineering at Meta
C
Cybersecurity and Infrastructure Security Agency CISA
aimingoo的专栏
aimingoo的专栏
Know Your Adversary
Know Your Adversary
Cyberwarzone
Cyberwarzone
Martin Fowler
Martin Fowler
The Hacker News
The Hacker News
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
G
GRAHAM CLULEY
宝玉的分享
宝玉的分享
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
S
Securelist
T
The Exploit Database - CXSecurity.com
T
Threatpost
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
F
Full Disclosure

ImageKit.io Blog

Next.js Image Optimization with ImageKit Use Video as a Background in Your Next.js Project How to Fix Autoplay Video in Next.js How Durian Scaled a Visual-First Retail Experience to 350K Monthly Visitors Online How Matsmart accelerated image delivery across countries with ImageKit AI in Digital Asset Management: From Smart Workflows to Agentic Automation How Joseph Joseph unified and secured global video delivery with ImageKit How Modall powers fast, effortless media delivery across 40+ projects with ImageKit Digital Asset Management (DAM) Trends: 2026 Report How to add a poster image to Video.js player (and automate it) HLS streaming with Video.js + React Building the future of storytelling with fast, AI-powered video delivery How PushOwl delivers 100M+ image-rich notifications seamlessly with ImageKit How Homify delivers millions of interior design images seamlessly with ImageKit Better event discovery with lightning‑fast videos & images Adding video player in React Native Video player in Angular applications Crop and resize videos in React Next.js image and video upload React image and video upload React video optimization How we quadrupled our traffic to 625K monthly page views How Apollo 24|7 boosted performance & reduced costs with ImageKit Simplify your media workflows with ImageKit DAM integrations Extending Lighthouse for custom image and video optimization analysis Brand Asset Management: What is it? How does it work? WordPress Digital Asset Management Guide - Manage your WP media assets better Why Shopify retailers need a digital asset management solution DAM vs. SharePoint: Which is best for you? AI-powered Metadata and Tagging in Digital Asset Management How Hopscotch built India's largest online Kids' fashion brand with ImageKit Dropbox Vs. DAM: Which Is The Right Tool For Digital Asset Management Digital Asset Management for Photographers: A Complete Guide Why digital asset management for agencies is essential Helping both Top and Bottom Line: SaffronStays rapid, profitable growth with ImageKit How KreditBee simplified media experiences with ImageKit Google Drive alternatives for businesses (with fast-growing teams) Node.js image upload ImageKit: The Secret Ingredient in Swiggy’s Expansion Journey Streamlining the Design Approval Process: A Comprehensive Guide AV1 Codec - Complete guide for video application devs PHP image and video upload Angular image & video upload AV1 vs VP9: Which codec should you choose? Adding video player in Next.js React Video Player VP8 vs VP9 - In the context of online video delivery Exploring WebM vs MP4 7 Free Digital Asset Management Software that are not Open-Source Comparing 9 Top Digital Asset Management Tools in the Market What are Brand Standards and Why do they Matter? Boost Sales and Brand Appeal: Essential Tips for eCommerce Image Management Brand Recall: The Strategy to Create Unforgettable Brands How to upload files in HTML? Branding for Small Businesses (2025 Edition) Everything you need to know about VP9 codec Recent updates from ImageKit and what's next Best Ways to Write RFP For Digital Asset Management (+ with free RFP template) What is Brand Dilution? How to Avoid It? Explained with [Examples] The Importance of Brand Identity: Leveraging Digital Asset Management for Impact From Launch to Scale: How to Launch a Brand Campaign Digital Asset Management Requirements - What do You Need to Evaluate and How? Marketing Collateral Management: A Quick End-to-End Guide Video Content Management System: What Is It And How To Choose One? Dropbox vs. Google Drive vs. Onedrive: The Best Cloud Storage Solution How to Build Brand Trust: Get Started In 2025 Google Drive vs. Box: A Detailed Comparison How Digital Asset Management Solutions Help Protect Brand Equity A DAM Solution Can Safeguard Your Digital Intellectual Property - Here’s How WebP Vs. PNG: Which Image Format Should You Use and Why? How to Resize Images in Bootstrap Easily Progressive jpegs (PJPEG): the key to loading images faster on your website Dropbox vs. Google Drive: The Best Cloud Storage For Digital Assets Dropbox Pros & Cons In 2024: An In-Depth Analysis and Why A DAM Solution Stands Out Google Drive Vs OneDrive: The Better Storage Option For Digital Assets Manage your video assets better with video metadata Understanding DAM's Role in Strengthening Brand Identity Digital asset management strategy: What to know before creating one The Ultimate Guide To Marketing Agency Onboarding 6 Solutions To Simplify Large File Sharing Over The Web A Step-by-Step Breakdown of a Video Production Workflow 13 Digital Asset Management Use Cases You Should Know How to Conduct a Brand Audit and Manage Your Brand Assets Costly Consequences of Inconsistent Branding And How DAM Can Help Dynamic Asset Transformation: What It Is, Why You Need It, and How ImageKit Can Help Everything You Need to Know About HTML Video Autoplay How To Select Your DAM Vendor: A Complete Guide How to Boost User Experience with Smart Digital Asset Management React Image Optimization: A Guide for Web Developers Why Should DAM Be A Part Of Your MarTech Stack? Unleashing the Power of Content Repurposing with ImageKit MKV vs MP4: Which Video File Format Is Better for Your Needs? Digital Asset Management For Ecommerce: A Complete Guide How an Image Tagging Software can Transform Your Image Search How to Manage Your Content Lifecycle Effectively M4V vs MP4: Which Video Format Should You Use and Why? Why Every Business Needs An Image Management System All The Questions To Ask During A Dam Demo Which is the Best Image Format for Your Website? Uploading Multiple Files Using JavaScript: A Comprehensive Guide
How to add shoppable videos to your Next.js site with ImageKit
Angel Pichardo · 2026-04-29 · via ImageKit.io Blog

A product photo on a category page does one job: grab the customer's focus. Once a shopper clicks through, the product page has to do everything else. Show the product in motion, build confidence, surface variants, and hand off to checkout without losing attention.

A static hero image and copy can only do so much. Shoppable videos close the gap between discovery and purchase. The viewer presses play, products appear on a bar alongside the video, items get highlighted as they appear on screen, and clickable markers on the video frame itself let the viewer jump straight to the product page — without pausing to search for it.

Building this from scratch usually means stitching together a video player, a product overlay system, a state machine to sync product highlights with playback time, and analytics on top. ImageKit's Video Player SDK ships all of it as a single config object.

In this tutorial we'll add a shoppable hero video to a Next.js product page using the SDK. By the end you'll have a working player with a three-product bar, time-based highlighting, clickable hotspots on the frame, and a post-play product carousel.

What we'll cover:

  1. Install and configure the ImageKit Video Player SDK
  2. Render a basic player on a product page
  3. Add the shoppable products bar with time-based highlighting
  4. Configure click-through actions
  5. Add clickable hotspots on the video frame

Setting up the ImageKit Video Player SDK

Install the package in a Next.js 15+ / React 18+ project:

npm install @imagekit/video-player

Add your ImageKit ID to .env.local:

NEXT_PUBLIC_IMAGEKIT_ID=your-imagekit-id

You can find your ImageKit ID in the dashboard under URL endpoint.

The Player SDK uses browser APIs, so any component that renders it needs "use client" in the App Router. Here's a minimal player to confirm the install works:

"use client";

import { IKVideoPlayer } from "@imagekit/video-player/react";
import "@imagekit/video-player/styles.css";

const ikOptions = {
  imagekitId: process.env.NEXT_PUBLIC_IMAGEKIT_ID!,
};

const source = {
  src: "https://ik.imagekit.io/your-id/field-jacket.mp4",
};

export default function ProductHero() {
  return <IKVideoPlayer ikOptions={ikOptions} source={source} />;
}

Drop this component into your product page and you should see a working player with default controls. If the video doesn't load, double-check that the source URL is publicly accessible from your ImageKit account.

If you're comparing the SDK to the HTML5 <video> element or VideoJS, Adding video player in Next.js walks through those options first.

Adding the shoppable products bar

The shoppable feature is a property on the source object. It takes an array of products, each with a name, image, and timing information that controls when the product gets highlighted in the bar.

Start by defining the product data. Keeping it in a separate file makes the player component easier to read.

// lib/products.ts
export const PRODUCTS = [
  {
    productId: 1,
    productName: "Field Jacket",
    imageUrl:
      "https://ik.imagekit.io/your-id/field-jacket.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 0, end: 6 },
    productUrl: "https://atlasgoods.example.com/field-jacket",
  },
  {
    productId: 2,
    productName: "Trail Pack",
    imageUrl:
      "https://ik.imagekit.io/your-id/trail-pack.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 5, end: 12 },
    productUrl: "https://atlasgoods.example.com/trail-pack",
  },
  {
    productId: 3,
    productName: "Trail Cap",
    imageUrl:
      "https://ik.imagekit.io/your-id/trail-cap.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 11, end: 18 },
    productUrl: "https://atlasgoods.example.com/trail-cap",
  },
];

The product images here use ImageKit's URL-based image transformations directly. tr=w-200,h-200,fo-auto resizes each image to a 200x200 thumbnail with smart crop centered on the subject. No image SDK needed for this.

highlightTime.start and highlightTime.end are seconds into the video. When playback enters the highlight window for a product, the SDK visually emphasizes that product in the bar. Slight overlaps between products are fine and create a smooth handoff as one product fades out and the next fades in.

Now wire the products into the player:

"use client";

import { IKVideoPlayer } from "@imagekit/video-player/react";
import "@imagekit/video-player/styles.css";
import { PRODUCTS } from "@/lib/products";

const ikOptions = {
  imagekitId: process.env.NEXT_PUBLIC_IMAGEKIT_ID!,
};

const source = {
  src: "https://ik.imagekit.io/your-id/field-jacket.mp4",
  shoppable: {
    products: PRODUCTS.map((p) => ({
      productId: p.productId,
      productName: p.productName,
      imageUrl: p.imageUrl,
      highlightTime: p.highlightTime,
      onClick: {
        action: "goto" as const,
        pause: true,
        args: { url: p.productUrl },
      },
    })),
    startState: "openOnPlay" as const,
    autoClose: 3,
    width: 22,
    showPostPlayOverlay: true,
  },
};

export default function ShoppableHero() {
  return <IKVideoPlayer ikOptions={ikOptions} source={source} />;
}

That's the shoppable feature in one config object. Press play and the bar opens on the right side of the player. Each product highlights in turn as playback hits its highlightTime window. Clicking a product pauses the video and navigates to the product page.

Here's what each shoppable option does:

OptionPurpose
productsArray of products to show in the bar. Each needs productId, productName, and imageUrl; highlightTime, onClick, onHover, and hotspots are all optional.
startStateWhen the bar opens. 'openOnPlay' reveals it as soon as the viewer presses play. Other values: 'closed', 'open'. Default: 'openOnPlay'.
autoCloseNumber of seconds before the product bar automatically closes after no user interaction. Default: 2.
widthWidth of the bar as a percentage of the player. 20-25 keeps the video readable on mobile. Default: 20.
showPostPlayOverlayWhen playback ends, show a product carousel over the player so viewers have one more chance to click through. Default: false.
transformationArray of ImageKit transformations applied to every product image in the bar. Handy for forcing a uniform size like [{ width: 200, height: 200 }].

The TypeScript as const annotations on action and startState are intentional. The SDK uses string-literal union types for these options, so the values need to be narrowed. For example 'goto' | 'seek' | 'overlay' | 'switch'.

ℹ️

The ImageKit Video Player SDK is currently in beta. Test thoroughly before using it in production, and pin to a specific version rather than latest.

Choosing the right click-through action

onClick.action controls what happens when a viewer clicks a product in the bar. Four options cover the common patterns:

ActionUse case
gotoNavigate to a URL. Best for sending viewers to a full product page.
seekJump to a different timestamp in the same video. Useful for a chapter-style "see this product in detail" interaction.
overlayShow a custom HTML message over the video without leaving the page. Good for "added to cart" confirmations or quick info.
switchSwap the product's thumbnail in the bar with an alternate image URL. Pair with onHover for "preview alternate color" interactions.

The example above uses goto for the standard "click product, go to product page" behavior. pause: true pauses the video before navigating so the viewer can resume from where they left off if they come back.

pause also accepts a number. pause: 2 pauses for two seconds, then resumes automatically. Useful when the click triggers an overlay action like "added to cart" and you want playback to continue once the toast fades.

For a more interactive experience, you can combine onHover and onClick. For example, "hover" swaps the product image to an alternate color and "click" navigates:

onHover: {
  action: "switch" as const,
  args: { url: "https://ik.imagekit.io/your-id/field-jacket-olive.jpg" },
},
onClick: {
  action: "goto" as const,
  pause: true,
  args: { url: p.productUrl },
},

Adding clickable hotspots on the video frame

The product bar is one part of the shoppable feature. Hotspots are the other. A hotspot is a clickable marker placed directly on the video frame at a specific timestamp, x/y coordinate, and tooltip position. When a viewer clicks a product in the bar, the video pauses at the hotspot's time and the marker appears on the frame.

This is the difference between "see related products in a sidebar" and "tap the jacket the model is wearing." The interaction maps directly to what the viewer sees on screen.

Update lib/products.ts to add a hotspots array to each product:

// lib/products.ts
export const PRODUCTS = [
  {
    productId: 1,
    productName: "Field Jacket",
    imageUrl: "https://ik.imagekit.io/your-id/field-jacket.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 0, end: 6 },
    productUrl: "https://atlasgoods.example.com/field-jacket",
    hotspots: [
      {
        time: "00:02",
        x: "42%",
        y: "55%",
        clickUrl: "https://atlasgoods.example.com/field-jacket",
        tooltipPosition: "right",
      },
    ],
  },
  {
    productId: 2,
    productName: "Trail Pack",
    imageUrl: "https://ik.imagekit.io/your-id/trail-pack.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 5, end: 12 },
    productUrl: "https://atlasgoods.example.com/trail-pack",
    hotspots: [
      {
        time: "00:08",
        x: "60%",
        y: "60%",
        clickUrl: "https://atlasgoods.example.com/trail-pack",
        tooltipPosition: "left",
      },
    ],
  },
  {
    productId: 3,
    productName: "Trail Cap",
    imageUrl: "https://ik.imagekit.io/your-id/trail-cap.jpg?tr=w-200,h-200,fo-auto",
    highlightTime: { start: 11, end: 18 },
    productUrl: "https://atlasgoods.example.com/trail-cap",
    hotspots: [
      {
        time: "00:14",
        x: "50%",
        y: "30%",
        clickUrl: "https://atlasgoods.example.com/trail-cap",
        tooltipPosition: "bottom",
      },
    ],
  },
];

Each hotspot has four key fields:

FieldPurpose
timeWhen the hotspot appears, formatted as "MM:SS". The video pauses at this point when the product is clicked from the bar.
x / yPosition on the video frame as percentage strings. "50%" / "40%" is roughly center, slightly above middle.
clickUrlURL the marker links to. Often the same as productUrl.
tooltipPositionWhere the product info tooltip appears relative to the marker. "left", "right", "top", "bottom".

Pass hotspots through in the player config:

shoppable: {
  products: PRODUCTS.map((p) => ({
    productId: p.productId,
    productName: p.productName,
    imageUrl: p.imageUrl,
    highlightTime: p.highlightTime,
    onClick: {
      action: "goto" as const,
      pause: true,
      args: { url: p.productUrl },
    },
    hotspots: p.hotspots,
  })),
  // ...same options as before
},

That's the full shoppable feature wired up.

ℹ️

Hotspot positions are tied to specific frames in your video. If you re-edit the source video and the timing or framing changes, the hotspot coordinates need to be adjusted to match.

Putting it together on a product page

The full page is small. A product header above the player, the shoppable component, and whatever else your product detail page would normally include below.

// app/page.tsx
import ShoppableHero from "@/components/ShoppableHero";

export default function ProductPage() {
  return (
    <main className="max-w-6xl mx-auto px-6 py-10">
      <header className="mb-8">
        <p className="text-sm uppercase tracking-widest text-zinc-500">
          Atlas Goods
        </p>
        <h1 className="text-4xl font-semibold mt-1">Field Jacket</h1>
        <p className="text-zinc-600 mt-2">
          Built for cold mornings and long miles. $248.
        </p>
      </header>

      <ShoppableHero />
    </main>
  );
}

That's the whole tutorial. A working shoppable product page in three files: the player component, the product data, and the page that renders them.

What we built

The page now does what would normally take three or four vendors stitched together. A modern HTML5 video player, a product bar synchronized with playback time, clickable hotspots on the video frame, and a post-play product carousel. All of it from one config object on the source prop.

For the broader picture of what the Video Player SDK supports beyond shoppable, the overview docs cover AI-generated subtitles and chapters, playlists, floating playback, and seek thumbnails, all configurable from the same source config you just used. The full reference for the shoppable options used above lives in the shoppable videos guide.

Sign up for a free ImageKit account and try the shoppable feature on a product video you already have.