React & Next.js SDK

Full reference for @onramp-sdk/react. Works with React 18+, Next.js App Router, and Next.js Pages Router.


Installation

bash
npm install @onramp-sdk/react

Setup

Next.js App Router

Add OnRampProvider to your root layout. It initializes once on the client and is SSR-safe - it no-ops on the server.

tsx
// app/layout.tsx
import { OnRampProvider } from '@onramp-sdk/react'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <OnRampProvider apiKey="onr_xxxxxxxxxxxx" appVersion="2.4.1">
          {children}
        </OnRampProvider>
      </body>
    </html>
  )
}

React (Vite, CRA, etc.)

tsx
// main.tsx
import { createRoot } from 'react-dom/client'
import { OnRampProvider } from '@onramp-sdk/react'
import App from './App'

createRoot(document.getElementById('root')!).render(
  <OnRampProvider apiKey="onr_xxxxxxxxxxxx" appVersion="2.4.1">
    <App />
  </OnRampProvider>
)

Your API key is on the Settings page of each app in the dashboard.

OnRampProvider props

PropTypeRequiredDefaultDescription
apiKeystringYes-Your API key from Settings
appVersionstringNo-Version string, e.g. "2.4.1" - shows in the version breakdown
frameworkstringNo'react'Label shown in the dashboard - set 'nextjs' to distinguish surfaces
sessionTimeoutMsnumberNo1_800_000Idle time (ms) before a new session starts (default 30 min)
anonymousIdMaxAgeMsnumberNo31_536_000_000How long before the anonymous ID rotates (default 365 days)
hoststringNo-Override ingestion endpoint (for self-hosting)

Tracking steps

useTrackStep(name, options?)

Fires a funnel milestone the moment the component mounts. Re-fires if name changes.

tsx
'use client'
import { useTrackStep } from '@onramp-sdk/react'

function ProfileSetup() {
  useTrackStep('profile_setup_viewed')
  return <form>...</form>
}

Options

OptionTypeDescription
propertiesRecord<string, string | number | boolean>Custom key-value data attached to the event
enabledbooleanSkip tracking while false - useful for gating on a loaded/ready state (default true)
tsx
// Only track once data has loaded
useTrackStep('checkout_viewed', {
  enabled: !!user,
  properties: { plan: user?.plan },
})

useOnRamp()

Returns the tracker API from any client component below <OnRampProvider>.

tsx
'use client'
import { useOnRamp } from '@onramp-sdk/react'

function UpgradeButton() {
  const { step, getIds } = useOnRamp()

  async function handleClick() {
    step('upgrade_clicked', { properties: { plan: 'pro' } })

    // Pass IDs to your server to fire backend events tied to this session
    const { anonymousId, sessionId } = getIds()
    await fetch('/api/checkout', {
      method: 'POST',
      body: JSON.stringify({ anonymousId, sessionId, plan: 'pro' }),
    })
  }

  return <button onClick={handleClick}>Upgrade</button>
}

API

MethodDescription
step(name, options?)Record a funnel milestone
identify(traits)Associate the current user with known traits for integration matching (optional)
flush()Flush queued events immediately (also runs on tab close)
newSession()Force-start a new session - call after logout
getIds()Returns { anonymousId, sessionId } for server-side event correlation

identify(traits)

Associates the current anonymous user with known identity traits. Call once after sign-in so integrations (Stripe, RevenueCat) can match the user to external records.

tsx
'use client'
import { useOnRamp } from '@onramp-sdk/react'

function AuthCallback({ user }: { user: User }) {
  const { identify } = useOnRamp()

  useEffect(() => {
    identify({ email: user.email, userId: user.id })
  }, [user.id])
}

identify() is entirely optional. Omit it if you have no integrations connected, or if users in your app prefer not to share identity traits. All funnel and retention features work without it.


Route tracking (Next.js App Router)

OnRampRouteTracker auto-records every App Router navigation as a nav_entered event. These appear in session timelines and the journey map but are kept out of your defined funnels automatically.

Mount it once inside OnRampProvider in your root layout:

tsx
// app/layout.tsx
import { OnRampProvider } from '@onramp-sdk/react'
import { OnRampRouteTracker } from '@onramp-sdk/react/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <OnRampProvider apiKey="onr_xxxxxxxxxxxx" framework="nextjs">
          <OnRampRouteTracker />
          {children}
        </OnRampProvider>
      </body>
    </html>
  )
}

OnRampRouteTracker is exported from @onramp-sdk/react/next (a separate entry point) so that non-Next.js React apps don't pull in the next package.


Session management

Call newSession() after logout so the next user gets a clean session:

tsx
'use client'
import { useOnRamp } from '@onramp-sdk/react'

function LogoutButton() {
  const { newSession } = useOnRamp()

  async function handleLogout() {
    await signOut()
    newSession()
  }

  return <button onClick={handleLogout}>Sign out</button>
}

Storage

Anonymous IDs and session state are stored in localStorage under @onramp/anonymous_id and @onramp/session. No HTTP cookies are set.

No HTTP cookies, but consent may still apply

OnRamp uses localStorage, not HTTP cookies, so browser-level cookie blocking won't affect it. However, the EU ePrivacy Directive covers all client-side storage for analytics - EU/UK developers should include OnRamp in their consent flow and initialise the SDK only after consent is granted. See the Privacy & data page for the full breakdown.


TypeScript

The SDK ships full TypeScript types. No @types/ package needed.

ts
import type { OnRampApi } from '@onramp-sdk/react'

function MyComponent() {
  const onramp: OnRampApi = useOnRamp()
  // ...
}