An interactive video-guided tour system for web applications
npm install saltfishInteractive video-guided tours for web applications. Create engaging onboarding experiences with synchronized video playback, interactive overlays, and smart triggering.


- 🎥 Video-Guided Tours - Synchronized video content with interactive UI overlays
- 🎯 Smart Triggers - Automatic playlist triggering based on URL, user behavior, and custom conditions
- 📱 Responsive - Automatically adapts to different screen sizes and devices
- 🎨 Shadow DOM - Complete style isolation prevents CSS conflicts
- 📊 Analytics - Built-in tracking for user engagement and completion rates
- 🔄 State Persistence - Resume tours where users left off
- 🌐 Multi-language - User-specific language preferences
- ⚡ Lightweight - Minimal bundle size with efficient loading
``html`
`bash`
npm install saltfish
`html
Welcome to My App
`
`javascript
import saltfish from 'saltfish';
// Initialize
saltfish.init({
token: 'YOUR_TOKEN_HERE',
enableAnalytics: true
});
// Identify user
saltfish.identify('user-123', {
email: 'user@example.com',
language: 'en'
});
// Start playlist
saltfish.startPlaylist('playlist-id');
`
Initialize the Saltfish player. Must be called before any other methods.
Parameters:
- config (Object or String):token
- If string: Your API token
- If object:
- (String, required): Your API token from Saltfish dashboardenableAnalytics
- (Boolean, optional): Enable/disable analytics tracking (default: true)
Returns: Promise (can be called without await)
Examples:
`javascript
// Simple initialization with token only
saltfish.init('YOUR_TOKEN_HERE');
// With configuration object
saltfish.init({
token: 'YOUR_TOKEN_HERE',
enableAnalytics: false // Disable analytics for development
});
// Using async/await
await saltfish.init('YOUR_TOKEN_HERE');
// Using events
saltfish.on('initialized', () => {
console.log('Saltfish ready!');
});
saltfish.init('YOUR_TOKEN_HERE');
`
Identify the current user. This enables playlist triggers, progress tracking, and personalized experiences.
Parameters:
- userId (String, required): Unique identifier for the userattributes
- (Object, optional):email
- (String): User's email addressname
- (String): User's display namelanguage
- (String): Language preference ('en', 'sv', 'es', 'fr', 'de', or 'auto' for browser detection)
- Any custom attributes you want to track
Examples:
`javascript
// Basic identification
saltfish.identify('user-123');
// With email and name
saltfish.identify('user-123', {
email: 'user@example.com',
name: 'John Doe'
});
// With language preference
saltfish.identify('user-123', {
email: 'user@example.com',
language: 'sv' // Swedish
});
// Auto-detect language from browser
saltfish.identify('user-123', {
language: 'auto'
});
// With custom attributes
saltfish.identify('user-123', {
email: 'user@example.com',
plan: 'premium',
signupDate: '2024-01-15'
});
`
Identify anonymous users without backend communication. Uses localStorage for progress tracking and trigger evaluation.
Parameters:
- attributes (Object, optional): Same as identify() method
Examples:
`javascript
// Anonymous user with language preference
saltfish.identifyAnonymous({
language: 'en'
});
// Anonymous user with no data
saltfish.identifyAnonymous();
// With custom tracking data
saltfish.identifyAnonymous({
language: 'auto',
theme: 'dark'
});
`
Manually start a specific playlist. If a playlist is already running, it will be reset and the new one started.
Parameters:
- playlistId (String, required): The playlist ID from your Saltfish dashboardoptions
- (Object, optional):startNodeId
- (String): Start from a specific step instead of the beginningposition
- (String): Player position ('bottom-left' or 'bottom-right')
Returns: Promise (can be called without await)
Examples:
`javascript
// Basic usage
saltfish.startPlaylist('playlist-123');
// Start from a specific step
saltfish.startPlaylist('playlist-123', {
startNodeId: 'step-5'
});
// With custom position
saltfish.startPlaylist('playlist-123', {
position: 'bottom-right'
});
// Using async/await
await saltfish.startPlaylist('playlist-123');
// Using events
saltfish.on('playlistStarted', (data) => {
console.log('Started:', data.playlist.id);
});
saltfish.startPlaylist('playlist-123');
`
Listen to player events using on() and remove listeners with off().
#### saltfish.on(eventName, handler)
Register an event listener.
Available Events:
- 'initialized' - Player initialized successfully'playlistStarted'
- - Playlist has started playing'playlistEnded'
- - Playlist completed'playlistDismissed'
- - User dismissed/closed the playlist'stepStarted'
- - New step/video started'stepEnded'
- - Step/video completed'error'
- - An error occurred
Examples:
`javascript
// Listen for playlist completion
saltfish.on('playlistEnded', (data) => {
console.log('Playlist completed:', data.playlist.id);
console.log('Completion rate:', data.completionRate);
});
// Listen for step changes
saltfish.on('stepStarted', (data) => {
console.log('Now on step:', data.step.id);
});
// Listen for errors
saltfish.on('error', (data) => {
console.error('Player error:', data.message);
});
// Listen for initialization
saltfish.on('initialized', () => {
console.log('Player ready!');
});
`
#### saltfish.off(eventName, handler)
Remove an event listener.
Returns: boolean - true if listener was removed, false if not found
Example:
`javascript
function onPlaylistEnd(data) {
console.log('Playlist ended:', data.playlist.id);
}
// Add listener
saltfish.on('playlistEnded', onPlaylistEnd);
// Remove listener
saltfish.off('playlistEnded', onPlaylistEnd);
`
#### saltfish.getSessionId()
Get the current session ID.
Returns: String
`javascript`
const sessionId = saltfish.getSessionId();
console.log('Session ID:', sessionId);
#### saltfish.getRunId()
Get the current run ID (unique per playlist execution).
Returns: String | null
`javascript`
const runId = saltfish.getRunId();
console.log('Run ID:', runId);
#### saltfish.resetPlaylist()
Reset the current playlist to its initial state.
`javascript`
saltfish.resetPlaylist();
#### saltfish.destroy()
Destroy the player instance and clean up all resources.
`javascript`
saltfish.destroy();
#### saltfish.version()
Get the current Saltfish player version.
Returns: String
`javascript`
const version = saltfish.version();
console.log('Saltfish version:', version);
Playlists can be automatically triggered based on conditions you configure in the Saltfish CMS. No code changes needed!
#### URL-Based Triggers
Automatically show playlists when users visit specific URLs:
`javascript
// Just initialize and identify - triggers happen automatically
saltfish.init('YOUR_TOKEN');
saltfish.identify('user-123');
// Playlist will auto-trigger when user navigates to configured URLs
// e.g., "/dashboard", "/pricing", "/features/*"
`
CMS Configuration Examples:
- Exact match: /dashboard - Only triggers on exactly /dashboard/dashboard
- Contains: with "contains" mode - Triggers on /dashboard, /dashboard/settings, etc./products/*
- Wildcard: - Triggers on any product page/playlist-[0-9]+
- Regex: - Triggers on /playlist-1, /playlist-42, etc.
#### Element Click Triggers
Trigger playlists when users click specific elements:
`html
`
#### Conditional Triggers
Configure complex trigger logic in the CMS:
- Once per user: Show playlist only once, never again
- Seen/Not seen: Trigger based on whether user has seen other playlists
- A/B Testing: Show different playlists to different user segments
- Combine conditions: URL + click + seen/not seen with AND/OR logic
You can always manually start a playlist even if triggers are configured:
`javascript`
// Manually start any playlist
saltfish.startPlaylist('onboarding-tour');
`javascript
// Initialize on page load
saltfish.init({
token: 'YOUR_TOKEN',
enableAnalytics: true
});
// Identify user after signup
saltfish.identify(userId, {
email: userEmail,
language: 'auto',
plan: 'free'
});
// Backend triggers will automatically show onboarding
// when configured in CMS for new users
`
`javascript
saltfish.init('YOUR_TOKEN');
saltfish.identify(userId);
// Configure in CMS to trigger on /new-feature page
// Playlist auto-plays when user visits
`
`html
`
`javascript
// Different tours for different pages
saltfish.init('YOUR_TOKEN');
saltfish.identify(userId);
// Configure in CMS:
// - "/dashboard" → dashboard-tour
// - "/settings" → settings-tour
// - "/billing" → billing-tour
// Tours trigger automatically based on URL
`
`jsx
import { useEffect } from 'react';
import saltfish from 'saltfish';
function App() {
useEffect(() => {
// Initialize Saltfish
saltfish.init({
token: process.env.REACT_APP_SALTFISH_TOKEN,
enableAnalytics: true
});
// Identify user when auth state changes
if (user) {
saltfish.identify(user.id, {
email: user.email,
name: user.name,
language: 'auto'
});
}
// Cleanup on unmount
return () => {
saltfish.destroy();
};
}, [user]);
return
$3
`vue
Your App
`$3
`typescript
import { Component, OnInit, OnDestroy } from '@angular/core';
import saltfish from 'saltfish';@Component({
selector: 'app-root',
template: '
Your App'
})
export class AppComponent implements OnInit, OnDestroy {
ngOnInit() {
saltfish.init({
token: environment.saltfishToken,
enableAnalytics: true
}); if (this.authService.user) {
saltfish.identify(this.authService.user.id, {
email: this.authService.user.email,
language: 'auto'
});
}
}
ngOnDestroy() {
saltfish.destroy();
}
}
`$3
`javascript
// app/layout.js or pages/_app.js
'use client';import { useEffect } from 'react';
import saltfish from 'saltfish';
export default function RootLayout({ children }) {
useEffect(() => {
if (typeof window !== 'undefined') {
saltfish.init({
token: process.env.NEXT_PUBLIC_SALTFISH_TOKEN,
enableAnalytics: true
});
// Identify user if logged in
// saltfish.identify(userId, { email, language: 'auto' });
}
return () => {
if (typeof window !== 'undefined') {
saltfish.destroy();
}
};
}, []);
return
{children};
}
`TypeScript Support
Full TypeScript definitions included:
`typescript
import saltfish, { SaltfishAPI } from 'saltfish';// All methods are fully typed
saltfish.init({
token: 'YOUR_TOKEN',
enableAnalytics: true
});
saltfish.identify('user-123', {
email: 'user@example.com',
language: 'en'
});
saltfish.startPlaylist('playlist-id', {
startNodeId: 'step-2'
});
// Event handlers are typed
saltfish.on('playlistEnded', (data) => {
console.log(data.playlist.id); // Fully typed
console.log(data.completionRate);
});
``- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Opera 76+
1. Sign up at saltfish.ai
2. Get your token from the dashboard
3. Create playlists using the CMS
4. Configure triggers (optional) for automatic playback
5. Install Saltfish in your app
- 📧 Email: support@saltfish.ai
- 🐛 Issues: GitHub Issues
- 📚 Documentation: docs.saltfish.ai
PROPRIETARY - See LICENSE file for details.
---
Made with ❤️ by Saltfish AB