Documentation

Everything you need to integrate OnTheWay into your product.

Quick Start

  1. Create a project in the Dashboard
  2. Record your tour — enter your site URL, click through the elements you want to highlight
  3. Edit copy & positioning — adjust titles, descriptions, and popover placement
  4. 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

Terminal
npm install ontheway-sdk
app.js
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.

app/layout.tsx (Next.js) or App.tsx
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>
  )
}
PropTypeRequiredDescription
projectIdstringYour project ID from Dashboard
apiUrlstringAPI endpoint override
onComplete(taskId) => voidCalled when a tour finishes
onSkip(taskId, step) => voidCalled when user closes early

useOnTheWay Hook

Access the SDK from any component. Most flexible approach.

SettingsPage.tsx
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 ValueTypeDescription
otwOnTheWay | nullRaw SDK instance (access getTasks() etc.)
readybooleanTrue when config is loaded
start(slug)functionStart a tour by slug or ID
reset(slug)functionReset a specific tour
resetAll()functionReset 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.

layout.tsx
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>} />
PropTypeDefaultDescription
labelReactNode"?"Button content
titlestring"Help & Guides"Panel header text
positionstring"bottom-right"Fixed position on screen
classNamestringWrapper class
buttonClassNamestringCustom button class (overrides default style)

HelpTrigger Component

Wrap any element to make it start a specific tour on click. Great for contextual help links.

SettingsPage.tsx
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>
  )
}
PropTypeDescription
taskSlugstringTour slug or ID to trigger
childrenReactNodeClickable content
classNamestringOptional wrapper class

Vanilla JavaScript

For non-React projects, use the SDK class directly:

app.js
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

MethodDescription
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.

OnTheWay Built by Zoe