Events & Analytics

Odyssey collects behavioral analytics through a lightweight embed script that tracks how users navigate through your journeys. This guide covers the event types, how data is collected, and how the ingest API works.

Overview

Odyssey's analytics approach is designed to be:

  • Privacy-first - No PII or field values are collected
  • Non-invasive - Never blocks or modifies your application
  • Semantic - Tracks high-level behavior, not low-level interactions
  • Reliable - Uses best-effort delivery with buffering

All analysis and modeling happens server-side. The embed script is purely for data collection.

Event types

Odyssey tracks coarse-grained, semantic events that represent meaningful user actions:

Session events

Track the beginning and end of user sessions:

  • Name
    session_start
    Description

    Fired when a user begins a new journey session. A session represents a single attempt to complete a journey.

  • Name
    session_end
    Description

    Fired when a session completes or times out. Includes completion status and duration.

Navigation events

Track user movement through pages and steps:

  • Name
    page_view
    Description

    Fired when any page loads. Includes the page URL and title.

  • Name
    step_view
    Description

    Fired when a user enters a specific journey step. Includes the step identifier (stepKey).

Interaction events

Track field-level interactions without capturing values:

  • Name
    field_focus
    Description

    Fired when a user focuses on an input field. Includes the field identifier but not the value.

  • Name
    field_blur
    Description

    Fired when a user leaves an input field. Tracks engagement duration.

  • Name
    field_change
    Description

    Fired when a field value changes. Does not include the actual value, only that a change occurred.

Validation events

Track form validation issues:

  • Name
    validation_error
    Description

    Fired when client-side validation fails. Can include the field identifier and error type, but not user input.

Submission events

Track form submissions:

  • Name
    submit_attempt
    Description

    Fired when a user attempts to submit a form. Tracks the step and timestamp.

  • Name
    submit_success
    Description

    Fired when a submission succeeds. Indicates successful completion of that step.

Analytics events

Derived signals for advanced analysis:

  • Name
    dropoff_signal
    Description

    Fired when user behavior indicates likely abandonment (e.g., rapid navigation away, window close, extended inactivity).

The embed script

The Odyssey embed script is a lightweight JavaScript file that collects events and sends them to the ingest API.

Installation

Add the script tag to your journey pages:

<script
  src="https://odysseylabs.ai/embed/v1.js"
  data-org="your_org_slug"
  data-journey="your_journey_slug"
  data-endpoint="https://odysseylabs.ai/api/ingest"
  data-env="prod"
  data-debug="false"
  async
></script>

Configuration attributes

  • Name
    data-org
    Type
    string
    Description

    Your organization slug.

  • Name
    data-journey
    Type
    string
    Description

    The journey slug this page belongs to.

  • Name
    data-endpoint
    Type
    string
    Description

    The ingest API endpoint URL.

  • Name
    data-env
    Type
    string
    Description

    Environment: prod, staging, or dev. Defaults to prod.

  • Name
    data-debug
    Type
    boolean
    Description

    Enable console logging. Set to true for development. Defaults to false.

How it works

When the script loads:

  1. Reads configuration from the script tag's data attributes
  2. Creates identifiers:
    • Anonymous sessionId (UUID v4, per session)
    • Persistent clientId (stored in localStorage, across sessions)
  3. Records session_start event immediately
  4. Buffers events in memory as they occur
  5. Flushes events to the API:
    • When the buffer reaches a size threshold
    • On visibilitychange or pagehide events
    • Using navigator.sendBeacon when available for reliability

Manual tracking (optional)

For advanced use cases, the script exposes a minimal API:

// Track a custom event
window.JourneyEmbed.track('custom_event_type', {
  key: 'value'
})

// Force flush buffered events
window.JourneyEmbed.flush()

// Check embed version
console.log(window.JourneyEmbed.version)

Most applications won't need this - automatic tracking is sufficient.

The ingest API

Events are sent to the ingest endpoint in batches.

Endpoint

POST /api/ingest

Request format

Events are sent as a batch with context:

Ingest batch request

{
  "schemaVersion": 1,
  "context": {
    "orgKey": "your-org-slug",
    "journeyKey": "grant-application",
    "language": "en-US",
    "deviceClass": "desktop"
  },
  "events": [
    {
      "_tag": "session_start",
      "schemaVersion": 1,
      "id": "evt_abc123",
      "ts": "2024-01-15T10:30:00.000Z",
      "orgKey": "your-org-slug",
      "journeyKey": "grant-application",
      "sessionId": "sess_xyz789",
      "clientId": "client_def456",
      "url": "https://grants.example.com/apply",
      "referrer": "https://google.com",
      "embedVersion": "1.0.0"
    },
    {
      "_tag": "step_view",
      "schemaVersion": 1,
      "id": "evt_abc124",
      "ts": "2024-01-15T10:30:01.000Z",
      "orgKey": "your-org-slug",
      "journeyKey": "grant-application",
      "sessionId": "sess_xyz789",
      "clientId": "client_def456",
      "url": "https://grants.example.com/apply/eligibility",
      "stepKey": "eligibility-check",
      "embedVersion": "1.0.0"
    }
  ]
}

Authentication

The ingest endpoint does not require authentication for sending events, but it does:

  • Validate that the organization and journey exist
  • Check allowed origins (if configured)
  • Apply rate limiting per organization

Rate limiting

Rate limits are applied per organization and journey:

  • Default: 1,000 requests per hour
  • Configurable per organization
  • Unknown origins are rate-limited more aggressively (20 requests per minute)

If you exceed the rate limit, you'll receive a 429 Too Many Requests response.

Response

Success response

204 No Content

The API returns 204 with no body on success. Errors return appropriate status codes:

  • 400 Bad Request - Invalid event data or malformed JSON
  • 404 Not Found - Organization or journey not found
  • 429 Too Many Requests - Rate limit exceeded
  • 500 Internal Server Error - Server error

Privacy and data collection

Odyssey is designed with privacy as a core principle:

What is collected

  • Event types and timestamps
  • Step and field identifiers
  • Session and client IDs (anonymous)
  • Page URLs and referrers
  • Device class (mobile/desktop/tablet)
  • Browser language

What is NOT collected

  • Field values or user input
  • Personally identifiable information (PII)
  • Uploaded files or attachments
  • Form content
  • Cookies (except for clientId in localStorage)

The anonymous clientId allows tracking repeat users without identifying them.

CORS and allowed origins

For security, you can restrict which domains can send events:

Set allowed origins

curl -X PUT https://odysseylabs.ai/api/journeys/my-journey \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "allowedOrigins": [
      "https://myapp.com",
      "https://staging.myapp.com"
    ]
  }'

Events from other origins will be rejected with a 403 error.

Debugging

Enable debug mode during development:

<script
  src="https://odysseylabs.ai/embed/v1.js"
  data-org="your_org_slug"
  data-journey="your_journey_slug"
  data-endpoint="https://odysseylabs.ai/api/ingest"
  data-env="staging"
  data-debug="true"
  async
></script>

With debug mode enabled, the embed script logs events to the browser console:

[JourneyEmbed] session_start: sess_xyz789
[JourneyEmbed] step_view: eligibility-check
[JourneyEmbed] Flushing 5 events to API

Viewing analytics

Once events are flowing, view analytics in your dashboard:

  • Journey-level metrics (completion rate, time to complete)
  • Step-level metrics (drop-off rates, field interaction)
  • Session recordings (coming soon)
  • Cohort analysis (coming soon)

Was this page helpful?