Documentation
Everything you need to integrate OnTheWay into your product.
Quick Start
- Create a project in the Dashboard
- Record your tour — enter your site URL, click through the elements you want to highlight
- Edit copy & positioning — adjust titles, descriptions, and popover placement
- Install the SDK — choose one of the methods below
Installation
Choose your integration method:
📜 Script Tag
One line, zero config. Good for static sites.
⚛️ React
Provider + Hook + Components. Full control.
📦 NPM
Import as module. Works with any bundler.
Script Tag
Add one line before </body>:
<script src="https://cdn.jsdelivr.net/npm/ontheway-sdk/dist/cdn.global.js"
data-project="YOUR_PROJECT_ID"></script>The SDK auto-initializes and exposes window.ontheway globally.
NPM / Yarn / pnpm
npm install ontheway-sdk
import { OnTheWay } from 'ontheway-sdk'
const otw = new OnTheWay({ projectId: 'YOUR_PROJECT_ID' })
// Manually start a tour
otw.start('welcome-tour')React Integration
OnTheWay provides first-class React support with a Provider, Hook, and pre-built components.
Provider Setup
Wrap your app root with OnTheWayProvider. It initializes the SDK and makes it available to all child components.
import { OnTheWayProvider } from 'ontheway-sdk/react'
export default function RootLayout({ children }) {
return (
<OnTheWayProvider
projectId="YOUR_PROJECT_ID"
apiUrl="/api" // optional, defaults to same origin
onComplete={(taskId) => {
console.log('Tour completed:', taskId)
// e.g. track in analytics
}}
onSkip={(taskId, stepIndex) => {
console.log('Tour skipped at step:', stepIndex)
}}
>
{children}
</OnTheWayProvider>
)
}| Prop | Type | Required | Description |
|---|---|---|---|
| projectId | string | ✅ | Your project ID from Dashboard |
| apiUrl | string | — | API endpoint override |
| onComplete | (taskId) => void | — | Called when a tour finishes |
| onSkip | (taskId, step) => void | — | Called when user closes early |
useOnTheWay Hook
Access the SDK from any component. Most flexible approach.
import { useOnTheWay } from 'ontheway-sdk/react'
function SettingsPage() {
const { otw, ready, start, reset, resetAll } = useOnTheWay()
// Get all available tours
const tasks = ready ? otw?.getTasks() ?? [] : []
return (
<div>
<h2>Settings</h2>
{/* Build a custom help menu */}
<div className="help-section">
<h3>Available Guides</h3>
<ul>
{tasks.map(task => (
<li key={task.id}>
<button onClick={() => start(task.slug)}>
{task.slug} ({task.steps.length} steps)
</button>
</li>
))}
</ul>
</div>
{/* Trigger a specific tour */}
<button onClick={() => start('settings-guide')}>
Need help with settings?
</button>
{/* Reset controls */}
<button onClick={() => reset('welcome')}>
Replay welcome tour
</button>
<button onClick={resetAll}>
Reset all tours
</button>
</div>
)
}| Return Value | Type | Description |
|---|---|---|
| otw | OnTheWay | null | Raw SDK instance (access getTasks() etc.) |
| ready | boolean | True when config is loaded |
| start(slug) | function | Start a tour by slug or ID |
| reset(slug) | function | Reset a specific tour |
| resetAll() | function | Reset all tours |
HelpMenu Component
A ready-made floating help button. Renders a ? button that opens a panel listing all available tours. Users click to start any tour.
import { OnTheWayProvider } from 'ontheway-sdk/react'
import { HelpMenu } from 'ontheway-sdk/components'
export default function Layout({ children }) {
return (
<OnTheWayProvider projectId="YOUR_PROJECT_ID">
{children}
<HelpMenu />
</OnTheWayProvider>
)
}Customize appearance and position:
// Custom label, title, position
<HelpMenu
label="💡"
title="Product Guides"
position="bottom-left" // bottom-right | bottom-left | top-right | top-left
/>
// Custom button style via className
<HelpMenu
label="Help"
buttonClassName="bg-blue-500 text-white px-4 py-2 rounded-full shadow-lg"
/>
// Custom emoji label
<HelpMenu label={<span>📚</span>} />| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | "?" | Button content |
| title | string | "Help & Guides" | Panel header text |
| position | string | "bottom-right" | Fixed position on screen |
| className | string | — | Wrapper class |
| buttonClassName | string | — | Custom button class (overrides default style) |
HelpTrigger Component
Wrap any element to make it start a specific tour on click. Great for contextual help links.
import { HelpTrigger } from 'ontheway-sdk/components'
function SettingsPage() {
return (
<div>
<h2>Settings</h2>
{/* Wrap a link */}
<HelpTrigger taskSlug="settings-guide">
<a className="text-blue-500 cursor-pointer">
Don't know where to start? Follow the guide →
</a>
</HelpTrigger>
{/* Wrap a button */}
<HelpTrigger taskSlug="billing-tour">
<button className="btn">Billing Help</button>
</HelpTrigger>
{/* Wrap an icon */}
<HelpTrigger taskSlug="export-guide">
<span title="How to export">❓</span>
</HelpTrigger>
</div>
)
}| Prop | Type | Description |
|---|---|---|
| taskSlug | string | Tour slug or ID to trigger |
| children | ReactNode | Clickable content |
| className | string | Optional wrapper class |
Vanilla JavaScript
For non-React projects, use the SDK class directly:
import { OnTheWay } from 'ontheway-sdk'
const otw = new OnTheWay({
projectId: 'YOUR_PROJECT_ID',
onComplete: (taskId) => console.log('done:', taskId),
})
// Wait for ready
const check = setInterval(() => {
if (otw.isReady()) {
clearInterval(check)
console.log('Tours available:', otw.getTasks())
}
}, 100)
// Trigger manually
document.getElementById('help-btn')
.addEventListener('click', () => otw.start('welcome'))
// Or build a menu
const tasks = otw.getTasks()
tasks.forEach(task => {
const li = document.createElement('li')
li.textContent = task.slug
li.onclick = () => otw.start(task.slug)
document.getElementById('help-list').appendChild(li)
})API Reference
| Method | Description |
|---|---|
| start(slugOrId) | Start a tour by slug or task ID |
| reset(slugOrId) | Reset a tour so it can show again |
| resetAll() | Reset all tours for the project |
| getTasks() | Get array of available TaskConfig objects |
| isReady() | Check if SDK config has loaded |
Trigger Types
Configure when tours start in the Dashboard:
manual
Only starts when you call start(slug). Use for help menus, contextual triggers.
auto
Starts automatically on every matching page load. Stops after completion.
first-visit
Starts once on the user's first visit. Uses localStorage to track.
Events & Callbacks
const otw = new OnTheWay({
projectId: 'YOUR_PROJECT_ID',
// Called when a tour is fully completed
onComplete: (taskId) => {
console.log('Completed:', taskId)
analytics.track('tour_completed', { taskId })
},
// Called when user closes/skips before finishing
onSkip: (taskId, stepIndex) => {
console.log(`Skipped ${taskId} at step ${stepIndex}`)
analytics.track('tour_skipped', { taskId, stepIndex })
},
})Best Practices
- Keep tours short — 3-5 steps max. Users lose interest after that.
- Use clear, actionable copy — "Click here to create a project" > "This is the project button"
- Highlight interactive elements — buttons, inputs, links. Not static text.
- Add stable selectors — Use
data-ontheway-id="xxx"attributes so tours survive CSS changes. - Test after UI changes — selectors can break. Check the Dashboard for step health.
- Use URL targeting — restrict tours to specific pages via URL pattern matching.
Troubleshooting
Tour skips a step
The CSS selector can't find the element. Open the task editor to update the selector, or add a data-ontheway-id attribute to the target element.
Tour doesn't start
Check trigger type. For first-visit tours, the user may have already seen it. Call reset(slug) or resetAll() to clear state.
SDK not loading
Verify your projectId is correct. Check the browser console for network errors. Ensure the API endpoint is accessible.
useOnTheWay returns null
Make sure OnTheWayProvider wraps the component tree. The hook must be called inside a child of the Provider.
Built by Zoe