# Next.js Configuration (/docs/configuration) Next.js Configuration [#nextjs-configuration] The Journium Next.js SDK extends the [React SDK](/docs/react) with Next.js-specific optimizations including automatic route change tracking for both App Router and Pages Router. Next.js-Specific Setup [#nextjs-specific-setup] Provider Configuration [#provider-configuration] ```tsx title="app/layout.tsx" import { NextJourniumProvider } from '@journium/nextjs'; const journiumConfig = { publishableKey: process.env.NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY!, options: { debug: process.env.NODE_ENV === 'development', autoTrackPageviews: true, // Auto-tracks route changes autocapture: true } }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` ```tsx title="pages/_app.tsx" import type { AppProps } from 'next/app'; import { NextJourniumProvider } from '@journium/nextjs'; const journiumConfig = { publishableKey: process.env.NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY!, options: { debug: process.env.NODE_ENV === 'development', autoTrackPageviews: true, // Auto-tracks route changes autocapture: true } }; export default function App({ Component, pageProps }: AppProps) { return ( ); } ``` Configuration Options [#configuration-options] The `config` prop accepts a `JourniumConfig` object with the same options as the JavaScript SDK. For detailed information about all available configuration options, see the [JavaScript SDK Configuration Guide](/docs/js/configuration). **Next.js-specific considerations:** * `autoTrackPageviews` - Set to `true` to automatically track Next.js route changes (recommended) * Environment variables should use `NEXT_PUBLIC_` prefix for client-side access * Configuration is SSR-compatible Next.js Components [#nextjs-components] [#nextjourniumprovider] Provider component with Next.js optimizations and automatic route tracking. **Props:** | Prop | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ---------------------- | | `config` | `JourniumConfig` | Yes | Configuration object | | `config.publishableKey` | `string` | Yes | Your publishable key | | `config.apiHost` | `string` | No | Custom API endpoint | | `config.options` | `JourniumLocalOptions` | No | Configuration options | | `children` | `ReactNode` | Yes | React children to wrap | **Next.js Features:** * ✅ Automatic route change detection (App Router and Pages Router) * ✅ SSR-compatible initialization * ✅ Works with `next/navigation` and `next/router` * ✅ Optimized for serverless deployments Automatic Route Tracking [#automatic-route-tracking] The Next.js provider automatically tracks route changes in both App Router and Pages Router: ```tsx // Automatically tracked: router.push('/products/123'); router.replace('/checkout'); About ``` **Disable automatic tracking:** ```tsx ``` Then manually track pageviews: ```tsx 'use client'; import { useTrackPageview } from '@journium/nextjs'; import { usePathname } from 'next/navigation'; import { useEffect } from 'react'; export function PageTracker() { const pathname = usePathname(); const trackPageview = useTrackPageview(); useEffect(() => { trackPageview({ pathname }); }, [pathname, trackPageview]); return null; } ``` React Hooks [#react-hooks] The Next.js SDK includes all React hooks. See the [React Hooks documentation](/docs/react/hooks) for details: * `useTrackEvent()` - Track custom events * `useIdentify()` - Identify users * `useReset()` - Reset user identity * `useTrackPageview()` - Manual pageview tracking * `useAutoTrackPageview()` - Automatic pageview tracking * `useAutocapture()` - Control autocapture * `useJournium()` - Access analytics instance Server-Side Rendering (SSR) [#server-side-rendering-ssr] The SDK is SSR-compatible and will not cause hydration issues: ```tsx // ✅ Safe in Next.js export default function Layout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` The analytics instance is only initialized on the client side. Environment Variables [#environment-variables] App Router / Pages Router [#app-router--pages-router] ```bash title=".env.local" NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=pk_your_key_here ``` ```tsx const config = { publishableKey: process.env.NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY! }; ``` Different Keys per Environment [#different-keys-per-environment] ```bash title=".env.local" # Development NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=pk_test_... # .env.production NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=pk_live_... ``` TypeScript Support [#typescript-support] The Next.js SDK is fully typed with the same types as the JavaScript SDK. For complete type definitions, see the [JavaScript SDK TypeScript Types](/docs/js/typescript-types) documentation. ```typescript import { type JourniumConfig, type JourniumLocalOptions, type AutocaptureOptions } from '@journium/nextjs'; ``` API Reference [#api-reference] For detailed API method reference, see the [JavaScript SDK API Methods](/docs/js/api-methods). The Next.js SDK provides the same methods through React hooks: | Hook | Underlying Method | Documentation | | ----------------- | ---------------------- | ---------------------------------------- | | `useTrackEvent()` | `analytics.track()` | [API Ref](/docs/js/api-methods#track) | | `useIdentify()` | `analytics.identify()` | [API Ref](/docs/js/api-methods#identify) | | `useReset()` | `analytics.reset()` | [API Ref](/docs/js/api-methods#reset) | Deployment Considerations [#deployment-considerations] Vercel [#vercel] Works out of the box. Environment variables are automatically available with `NEXT_PUBLIC_` prefix. Self-Hosted [#self-hosted] Ensure environment variables are configured: ```bash title=".env.production" NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=pk_live_... ``` Then build normally: ```bash npm run build ``` Next Steps [#next-steps] Learn about all available hooks for Next.js See all configuration options in detail Complete API method reference # How Journium Works (/docs/how-journium-works) Journium works by collecting [Events](/docs/concepts/events) from your application and then using AI to generate insights from those events. Users integrate the Journium SDK into their applications, which sends events to Journium's API where they are ingested and processed. Users then create [Insight Trackers](/docs/concepts/insight-trackers) that define the mechanics around how [Insights](/docs/concepts/insights) should be generated, and [Jobs](/docs/concepts/jobs) execute those trackers to produce insights. These insights are then available on the Journium dashboard for users to view and analyze. Journium Workflow [#journium-workflow] The diagram below illustrates the complete Journium workflow: Event Collection [#event-collection] Event collection is the foundation of Journium's analytics pipeline. Users integrate the Journium SDK into their applications, which acts as a lightweight client library that captures user interactions and application events. When events occur in your application—such as user signups, purchases, feature usage, or errors—the SDK automatically sends these events to Journium's API endpoint. The API receives and ingests these events, storing them in a time-series database optimized for analytics queries. This continuous stream of event data provides the raw material that powers all subsequent analysis and insight generation. Tracker Definition [#tracker-definition] Trackers are declarative configurations that define what should be analyzed and how insights should be generated. Users create trackers through the Journium dashboard, specifying which events to monitor (or analyzing all events), setting custom instructions for the AI analysis, and configuring execution schedules. Each tracker acts like a continuous data analyst that monitors specific patterns in your event data. Trackers can be set to run automatically on a schedule (e.g., hourly, daily, weekly) or triggered manually for ad-hoc analysis. The tracker configuration includes parameters such as the maximum number of events to analyze, custom AI instructions that guide the analysis focus, and the specific event types to consider. This "Insights as Code" approach allows users to define what they want to know about their application without writing SQL queries or building dashboards. Job Execution [#job-execution] Job execution is the automated process that runs trackers and generates insights. When a tracker is scheduled to run or manually triggered, Journium creates a job that executes the tracker's analysis workflow. The job execution follows a multi-step pipeline: it first validates the tracker configuration and checks data availability, then queries the event database to retrieve the relevant events based on the tracker's configuration. The job then uses AI to analyze the event data, looking for patterns, trends, anomalies, and correlations. The AI engine processes the data according to the tracker's instructions, synthesizing findings into concise, natural language insights that are typically 1-3 sentences long and backed by verifiable data. Finally, the job stores the generated insights and updates the execution history, making them ready for display in the dashboard. Insights Display [#insights-display] Once insights are generated by job execution, they become available in the Journium dashboard for users to view and analyze. Insights are displayed in a feed format on the application instance's insights page, similar to a social media feed, where each insight appears as a card showing the analysis results, timestamp, and metadata. Users can interact with insights by liking them, adding comments for team collaboration, saving them for later reference, or sharing them with team members. The dashboard also provides features like pagination to browse through historical insights, filtering options, and the ability to see insight trends over time. This presentation format makes insights easily scannable and actionable, transforming raw event data into understandable narratives that help teams make data-driven decisions about their application. # Journium Docs (/docs) import { NextJsIcon } from '@/components/icons/nextjs'; import { ReactIcon } from '@/components/icons/react'; import { AngularIcon } from '@/components/icons/angular'; import { JsIcon } from '@/components/icons/js'; Journium turns raw telemetry into proactive, narrative insights — without charts, queries, or BI. Find the right guide for your needs, whether you are just getting stated or looking to implement advanced features. } href="/docs/quick-start"> Get started with Journium in your Next.js application } href="/docs/react"> Integrate Journium into your React application } href="/docs/angular"> Add Journium tracking to your Angular application } href="/docs/js"> Add Journium tracking to your vanilla JavaScript application # Next.js Quick Start (/docs/quick-start) Setup [#setup] Set up Journium for your Next.js application.
Install @journium/nextjs [#install-journiumnextjs] The [Journium Next.js SDK](/docs/hooks) gives you access to pre-built hooks and components to help you generate events in your Next.js application and get insights from your data. Run the following command to install the SDK: npm pnpm yarn bun ```bash title="Terminal" npm i @journium/nextjs ``` ```bash title="Terminal" pnpm add @journium/nextjs ``` ```bash title="Terminal" yarn add @journium/nextjs ``` ```bash title="Terminal" bun add @journium/nextjs ``` Set your Journium Publishable Key [#set-your-journium-publishable-key] 1. **Sign up for a Journium account** for free at [journium.app/signup](https://journium.app/signup) 2. **[Create an application](https://dashboard.journium.app/apps/new)** in your Journium dashboard 3. **Copy your Publishable Key** from the [Developers | API Keys](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/api-keys) section Dashboard URLs automatically navigate to your app - just click! 4. **Create a `.env.local` file** in your project root: ```bash touch .env.local ``` 5. **Add your key** to the `.env.local` file: ```bash title=".env.local" NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=your_publishable_key_here ``` 6. **Verify your setup** - check that the key is correctly saved: ```bash cat .env.local # Should show: NEXT_PUBLIC_JOURNIUM_PUBLISHABLE_KEY=pk_test_... ``` Development instances use `pk_test_` keys. Production keys start with `pk_live_`. Add to your app [#add-nextjourniumprovider-to-your-app] The `` component provides session and user context to Journium's hooks. It's recommended to wrap your entire app at the entry point with `` to make analytics globally accessible throughout your application. ```tsx title="app/layout.tsx" // [!code ++:1] import { NextJourniumProvider } from '@journium/nextjs'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {/* [!code ++:1] */} {children} {/* [!code ++:1] */} ); } ``` ```tsx title="pages/_app.tsx" import type { AppProps } from 'next/app'; // [!code ++:1] import { NextJourniumProvider } from '@journium/nextjs'; export default function App({ Component, pageProps }: AppProps) { return ( {/* [!code ++:1] */} {/* [!code ++:1] */} ); } ``` Run the Development Server [#run-the-development-server] Start your application: npm pnpm yarn bun ```bash title="Terminal" npm run dev ``` ```bash title="Terminal" pnpm run dev ``` ```bash title="Terminal" yarn dev ``` ```bash title="Terminal" bun run dev ``` **Using a custom port?** Next.js defaults to port 3000. To use a different port, set the `PORT` environment variable or use `-p` flag: `npm run dev -- -p 3001` Verify Your Setup [#verify-your-setup] Open [http://localhost:3000](http://localhost:3000) (or your custom port) in your browser to see the application running. Send Events to Journium [#send-events-to-journium] Navigate around your app to automatically send events to Journium. Then view your collected events at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events). **Success indicator:** You should see events appearing in your dashboard within a few seconds. Generate Your First Insight [#generate-your-first-insight] When you create an app in Journium, a default [Insight Tracker](/docs/concepts/insight_trackers) is automatically created. This tracker helps you test data ingestion and insight generation. 1. Go to your [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) page 2. Click the **`Analyze now`** button for the tracker titled **"User Engagement"** 3. Monitor the job status in [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs) 4. Wait for the job to complete (usually takes 1-2 minutes) 5. View your generated insights at [Dashboard | Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) Done [#done] **Congratulations!** You've successfully created your first insight with Journium!
Troubleshooting [#troubleshooting] * Verify your API key starts with `pk_` and is correctly set in `.env.local` * Check browser console for errors (F12 → Console) * Ensure you're interacting with your **local app** (not the dashboard) * Restart the dev server after changing `.env.local` file * Delete `node_modules` and reinstall dependencies: ```bash rm -rf node_modules && npm install ``` * Ensure Node.js version is 18+: ```bash node --version ``` * Use a different port: ```bash npm run dev -- -p 3001 ``` * Or stop the process using the port: ```bash # macOS/Linux lsof -ti:3000 | xargs kill -9 ``` * Ensure the file is named exactly `.env.local` (not `.env.local.txt`) * Restart the development server after creating/modifying `.env.local` * Check file location: it must be in the project root, not in `app/` or `pages/` * For Next.js, environment variables must be prefixed with `NEXT_PUBLIC_` to be accessible in the browser What's next? [#whats-next] Learn how to send your own custom events to track user behavior. Create custom analytics and understand how insights are generated. # What is Journium (/docs/what-is-journium) import { RocketIcon } from 'lucide-react'; **Journium** turns raw telemetry into proactive, narrative insights — without charts, queries, or BI. Instead of asking humans to hunt through dashboards, Journium sits on top of your application's data and automatically detects meaningful behavioral changes, explains what happened, and surfaces insights in plain language. **Data exists. Awareness doesn't.** Journium flips that model. The Problem We're Solving [#the-problem-were-solving] Modern applications generate mountains of event data — every click, page view, transaction, and user interaction creates a data point. Yet despite this abundance of information, organizations struggle to extract clear, actionable insights in a timely manner. The Traditional Analytics Trap [#the-traditional-analytics-trap] The conventional approach to analytics follows a broken pattern: **Telemetry → Storage → Queries → Dashboards → Hope** Teams collect data, store it, build dashboards, and then... hope someone notices something important. This process demands: * **Manual exploration** — analysts must preprocess data, run queries, and interpret results * **Domain expertise** — understanding what to look for requires deep knowledge * **Significant time** — valuable knowledge often remains buried because generating insights traditionally requires significant manual effort * **Reactive discovery** — by the time an insight is found, it may be too late to act The result? **We have a data overload, but an insights shortage.** Busy product teams and executives rarely have the luxury to sift through dashboards or craft SQL queries on the fly. Important findings may be discovered too late or not at all. Why Dashboards Fall Short [#why-dashboards-fall-short] Static dashboards can show you *what* happened, but they rarely explain *why*. Even specialized BI tools struggle to surface the root causes behind metric movements. You're left with charts that require interpretation, correlation analysis, and often, a bit of guesswork. How Journium Flips the Narrative [#how-journium-flips-the-narrative] Journium reimagines analytics from the ground up. Instead of passive reporting tools, we've built an active system that acts like a data analyst working 24/7. The New Model: Telemetry → Meaning → Action [#the-new-model-telemetry--meaning--action] Journium follows a simple, powerful principle: **Telemetry → Meaning → Action** Not: Telemetry → Storage → Queries → Dashboards → Hope Your application doesn't need more dashboards. It needs a way to **speak up** when something meaningful changes. From Passive to Proactive [#from-passive-to-proactive] Traditional analytics asks: *"What do you want to know?"*\ Journium asks: *"What should you know?"* Instead of waiting for someone to query the data, Journium continuously monitors your application's behavior, detects significant changes, performs root-cause analysis, and delivers concise insights directly to you — in Slack, email, or wherever you need them. Think of it this way: Who has the time or interest to dig through charts if an AI can directly tell you *"users from segment X are churning due to feature Y issues, impacting conversion by Z%"* — with the data to back it up? Insights as Code: The Foundation [#insights-as-code-the-foundation] Journium introduces **"Insights as Code"** — a novel approach where insights are treated as a first-class, codified product, and an AI-driven engine transforms raw event data into human-ready insights. What This Means [#what-this-means] Just as Infrastructure as Code revolutionized how servers and networks are configured, Insights as Code brings software engineering rigor to analytics: * **Declarative specifications** — Define what you care about in code or configuration, not spreadsheets or Wiki pages * **Version-controlled** — Track changes, review insights, and maintain consistency across your team * **Automated generation** — Let AI do the heavy lifting of data crunching, pattern finding, and explanation generation * **Verifiable and transparent** — Every insight is backed by code and data, making it transparent and trustworthy The Power of AI-Driven Analysis [#the-power-of-ai-driven-analysis] Journium leverages Generative AI and large language models to automate insight generation. But this isn't about dumping data into an LLM and hoping for the best. Instead, we use a sophisticated, multi-step approach: 1. **Continuous monitoring** — Track behavioral patterns and detect significant changes 2. **Intelligent analysis** — Use AI agents to pose analytical questions, break them into sub-questions, query data, and synthesize findings 3. **Validation and guardrails** — Ensure insights are both interesting and trustworthy, with automatic validation of claims 4. **Concise delivery** — Generate short, factual takeaways (not long-winded reports) that get straight to the point This approach ensures insights are **concise, factual takeaways** rather than shallow observations or obvious outliers. The Vision: An Always-On System [#the-vision-an-always-on-system] Journium transforms analytics from a reactive process into an **always-on system** that actively drives growth. The vision is simple: 1. **Instrument once** — Integrate Journium's SDK into your application 2. **Define what matters** — Specify your goals and questions in configuration 3. **Receive insights automatically** — Get proactive, narrative insights delivered continuously The outcome? An analytics experience that feels almost magical: you integrate an SDK, define high-level goals in a config, and the system speaks to you with facts and explanations continuously — almost like a data-savvy colleague working around the clock. Yet under the hood, every insight is backed by code and data — transparent and verifiable. Why This Matters [#why-this-matters] In a world inundated with data, those who can harness AI to tell the story of the data will leap ahead. Journium eliminates the traditional divide between "data collection" and "insight generation," drastically reducing the time from question to answer and empowering teams to be truly data-driven without slogging through dashboards. The barrier to trying a new analysis becomes so low — just write a new tracker and let the AI do the rest. This unlocks creative uses of analytics that were previously too time-consuming or resource-intensive to pursue. **Stop looking for insights. Let your application tell you.** } href="/docs" horizontal="true"> Get Journium integrated into your app in under 5 minutes # Angular Configuration (/docs/angular/configuration) Angular Configuration [#angular-configuration] The Journium Angular SDK wraps the core [JavaScript SDK](/docs/js) and provides Angular-specific service and providers. Angular Version Compatibility [#angular-version-compatibility] `@journium/angular` requires **Angular 15 or later**. All APIs used (`makeEnvironmentProviders`, `inject()`, `APP_INITIALIZER`) have been stable since Angular 15. | Angular | Standalone API | NgModule API | Signals | Zoneless | | ------- | -------------- | ------------ | ------- | ---------------- | | 15 | ✅ | ✅ | — | — | | 16 | ✅ | ✅ | — | — | | 17 | ✅ | ✅ | ✅ | — | | 18 | ✅ | ✅ | ✅ | ✅ (experimental) | | 19 | ✅ | ✅ | ✅ | ✅ (experimental) | | 20 / 21 | ✅ | ✅ | ✅ | ✅ (experimental) | The SDK is **zone-agnostic**: no `NgZone`, no `ChangeDetectorRef` coupling. It works identically in zone.js, zoneless, and signal-based component trees. Angular-Specific Setup [#angular-specific-setup] Standalone App Configuration [#standalone-app-configuration] Use `provideJournium()` in `bootstrapApplication`: ```typescript title="src/main.ts" import { bootstrapApplication } from '@angular/platform-browser'; import { provideRouter } from '@angular/router'; import { provideJournium, withJourniumRouter } from '@journium/angular'; import { environment } from './environments/environment'; import { AppComponent } from './app/app.component'; import { routes } from './app/app.routes'; bootstrapApplication(AppComponent, { providers: [ provideJournium({ publishableKey: environment.journiumPublishableKey, options: { debug: !environment.production, autoTrackPageviews: true, autocapture: true, }, }), provideRouter(routes), withJourniumRouter(), // Auto-track pageviews on NavigationEnd ], }); ``` NgModule Configuration [#ngmodule-configuration] Use `JourniumModule.forRoot()` in your root module: ```typescript title="src/app/app.module.ts" import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; import { JourniumModule } from '@journium/angular/ngmodule'; import { environment } from '../environments/environment'; @NgModule({ imports: [ BrowserModule, RouterModule.forRoot(routes), JourniumModule.forRoot({ publishableKey: environment.journiumPublishableKey, options: { debug: !environment.production, autoTrackPageviews: true, autocapture: true, }, }), ], bootstrap: [AppComponent], }) export class AppModule {} ``` Configuration Options [#configuration-options] The `config` object passed to `provideJournium()` or `JourniumModule.forRoot()` accepts a `JourniumConfig` object: * `publishableKey` (required): Your Journium publishable key * `apiHost` (optional): Custom API endpoint * `options` (optional): Configuration options object For detailed information about all available configuration options, see the [JavaScript SDK Configuration Guide](/docs/js/configuration). **Common options:** * `debug` - Enable debug logging * `flushAt` - Number of events before auto-flush * `flushInterval` - Flush interval in milliseconds * `sessionTimeout` - Session timeout duration * `autoTrackPageviews` - Automatically track page views * `autocapture` - Configure automatic event capture Angular Providers [#angular-providers] provideJournium(config) [#providejourniumconfig] Returns `EnvironmentProviders` for use in `bootstrapApplication`. This is the recommended approach for standalone Angular 15+ apps. ```typescript import { provideJournium } from '@journium/angular'; bootstrapApplication(AppComponent, { providers: [ provideJournium({ publishableKey: 'pk_...' }), ], }); ``` withJourniumRouter() [#withjourniumrouter] Optional router integration. Subscribes to Angular Router `NavigationEnd` events and automatically calls `capturePageview()` on each navigation. ```typescript import { provideJournium, withJourniumRouter } from '@journium/angular'; import { provideRouter } from '@angular/router'; bootstrapApplication(AppComponent, { providers: [ provideJournium({ publishableKey: 'pk_...' }), provideRouter(routes), withJourniumRouter(), // Must come after provideRouter() ], }); ``` JourniumModule.forRoot(config) (NgModule pattern) [#journiummoduleforrootconfig-ngmodule-pattern] For Angular apps using NgModule, import `JourniumModule.forRoot()` once in your root module. This provides `JourniumService` application-wide via Angular's DI. JourniumService [#journiumservice] Inject `JourniumService` in any component or service. See the [JourniumService reference](/docs/angular/services/journium-service) for available methods. ```typescript import { JourniumService } from '@journium/angular'; @Component({ ... }) export class MyComponent { constructor(private journium: JourniumService) {} } ``` TypeScript Support [#typescript-support] The Angular SDK is fully typed. All types are re-exported from `@journium/angular`: ```typescript import { type JourniumConfig, type JourniumLocalOptions, type AutocaptureOptions, } from '@journium/angular'; ``` Next Steps [#next-steps] Learn about all JourniumService methods See all configuration options in detail Complete API method reference # How Journium Works (/docs/angular/how-journium-works) Journium works by collecting [Events](/docs/angular/concepts/events) from your application and then using AI to generate insights from those events. Users integrate the Journium SDK into their applications, which sends events to Journium's API where they are ingested and processed. Users then create [Insight Trackers](/docs/angular/concepts/insight-trackers) that define the mechanics around how [Insights](/docs/angular/concepts/insights) should be generated, and [Jobs](/docs/angular/concepts/jobs) execute those trackers to produce insights. These insights are then available on the Journium dashboard for users to view and analyze. Journium Workflow [#journium-workflow] Event Collection [#event-collection] Event collection is the foundation of Journium's analytics pipeline. Users integrate the Journium SDK into their applications, which acts as a lightweight client library that captures user interactions and application events. When events occur in your application—such as user signups, purchases, feature usage, or errors—the SDK automatically sends these events to Journium's API endpoint. The API receives and ingests these events, storing them in a time-series database optimized for analytics queries. This continuous stream of event data provides the raw material that powers all subsequent analysis and insight generation. Tracker Definition [#tracker-definition] Trackers are declarative configurations that define what should be analyzed and how insights should be generated. Users create trackers through the Journium dashboard, specifying which events to monitor (or analyzing all events), setting custom instructions for the AI analysis, and configuring execution schedules. Each tracker acts like a continuous data analyst that monitors specific patterns in your event data. Trackers can be set to run automatically on a schedule (e.g., hourly, daily, weekly) or triggered manually for ad-hoc analysis. The tracker configuration includes parameters such as the maximum number of events to analyze, custom AI instructions that guide the analysis focus, and the specific event types to consider. This "Insights as Code" approach allows users to define what they want to know about their application without writing SQL queries or building dashboards. Job Execution [#job-execution] Job execution is the automated process that runs trackers and generates insights. When a tracker is scheduled to run or manually triggered, Journium creates a job that executes the tracker's analysis workflow. The job execution follows a multi-step pipeline: it first validates the tracker configuration and checks data availability, then queries the event database to retrieve the relevant events based on the tracker's configuration. The job then uses AI to analyze the event data, looking for patterns, trends, anomalies, and correlations. The AI engine processes the data according to the tracker's instructions, synthesizing findings into concise, natural language insights that are typically 1-3 sentences long and backed by verifiable data. Finally, the job stores the generated insights and updates the execution history, making them ready for display in the dashboard. Insights Display [#insights-display] Once insights are generated by job execution, they become available in the Journium dashboard for users to view and analyze. Insights are displayed in a feed format on the application instance's insights page, similar to a social media feed, where each insight appears as a card showing the analysis results, timestamp, and metadata. Users can interact with insights by liking them, adding comments for team collaboration, saving them for later reference, or sharing them with team members. The dashboard also provides features like pagination to browse through historical insights, filtering options, and the ability to see insight trends over time. This presentation format makes insights easily scannable and actionable, transforming raw event data into understandable narratives that help teams make data-driven decisions about their application. # Angular Quick Start (/docs/angular) Setup [#setup] Set up Journium for your Angular application.
Install @journium/angular [#install-journiumangular] The [Journium Angular SDK](/docs/angular/services) gives you access to a `JourniumService`, Angular module, and provider functions to send events from your Angular application and get insights from your data. Run the following command to install the SDK: npm pnpm yarn bun ```bash title="Terminal" npm i @journium/angular ``` ```bash title="Terminal" pnpm add @journium/angular ``` ```bash title="Terminal" yarn add @journium/angular ``` ```bash title="Terminal" bun add @journium/angular ``` Set your Journium Publishable Key [#set-your-journium-publishable-key] 1. **Sign up for a Journium account** for free at [journium.app/signup](https://journium.app/signup) 2. **[Create an application](https://dashboard.journium.app/apps/new)** in your Journium dashboard 3. **Copy your Publishable Key** from the [Developers | API Keys](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/api-keys) section Dashboard URLs automatically navigate to your app - just click! 4. **Add your key** to `src/environments/environment.ts`: ```typescript title="src/environments/environment.ts" export const environment = { production: false, journiumPublishableKey: 'your_publishable_key_here', }; ``` Development instances use `pk_test_` keys. Production keys start with `pk_live_`. Initialize Journium in your app [#initialize-journium-in-your-app] The Journium Angular SDK supports both **standalone** (Angular 15+) and **NgModule** patterns. Add `provideJournium()` to your `bootstrapApplication` call in `src/main.ts`: ```typescript title="src/main.ts" import { bootstrapApplication } from '@angular/platform-browser'; import { provideRouter } from '@angular/router'; // [!code ++:2] import { provideJournium, withJourniumRouter } from '@journium/angular'; import { environment } from './environments/environment'; import { AppComponent } from './app/app.component'; import { routes } from './app/app.routes'; bootstrapApplication(AppComponent, { providers: [ // [!code ++:7] provideJournium({ publishableKey: environment.journiumPublishableKey, }), provideRouter(routes), // Optional: automatically track pageviews on each route change withJourniumRouter(), ], }); ``` Import `JourniumModule.forRoot()` in your root `AppModule`: ```typescript title="src/app/app.module.ts" import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; // [!code ++:2] import { JourniumModule } from '@journium/angular/ngmodule'; import { environment } from '../environments/environment'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, // [!code ++:3] JourniumModule.forRoot({ publishableKey: environment.journiumPublishableKey, }), ], bootstrap: [AppComponent], }) export class AppModule {} ``` Use JourniumService in your components [#use-journiumservice-in-your-components] Inject `JourniumService` to track events anywhere in your app: ```typescript title="src/app/pages/home.component.ts" import { Component } from '@angular/core'; // [!code ++:1] import { JourniumService } from '@journium/angular'; @Component({ selector: 'app-home', standalone: true, template: ` `, }) export class HomeComponent { // [!code ++:1] constructor(private journium: JourniumService) {} handleClick(): void { // [!code ++:4] this.journium.track('button_clicked', { page: 'home', button_text: 'Track Event', }); } } ``` Run the Development Server [#run-the-development-server] Start your application: ```bash title="Terminal" ng serve ``` **Using a custom port?** Pass `--port 4200` to the serve command. The default Angular port is `4200`. Verify Your Setup [#verify-your-setup] Open [http://localhost:4200](http://localhost:4200) in your browser. Interact with your app to generate events. Send Events to Journium [#send-events-to-journium] Navigate around your app to automatically send events to Journium. Then view your collected events at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events). **Success indicator:** You should see events appearing in your dashboard within a few seconds. Generate Your First Insight [#generate-your-first-insight] When you create an app in Journium, a default [Insight Tracker](/docs/angular/concepts/insight_trackers) is automatically created. This tracker helps you test data ingestion and insight generation. 1. Go to your [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) page 2. Click the **`Analyze now`** button for the tracker titled **"User Engagement"** 3. Monitor the job status in [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs) 4. Wait for the job to complete (usually takes 1-2 minutes) 5. View your generated insights at [Dashboard | Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) Done [#done] **Congratulations!** You've successfully created your first insight with Journium!
Troubleshooting [#troubleshooting] * Verify your publishable key starts with `pk_` and is correctly set in `environment.ts` * Check browser console for errors (F12 → Console) * Ensure you're interacting with your **local app** (not the dashboard) * Restart the dev server after changing `environment.ts` * Delete `node_modules` and reinstall: ```bash rm -rf node_modules && npm install ``` * Ensure Angular 15+ is installed: ```bash ng version ``` * Verify `experimentalDecorators: true` is set in your `tsconfig.json` * Ensure `provideJournium()` is called in `bootstrapApplication` (standalone) or `JourniumModule.forRoot()` is imported in `AppModule` (NgModule) * `JourniumService` must be provided at the root level — not in a lazy-loaded module * Ensure `withJourniumRouter()` is included in the providers array alongside `provideRouter(routes)` * Both `provideRouter` and `withJourniumRouter` must be in the same `bootstrapApplication` call What's next? [#whats-next] Learn how to send your own custom events to track user behavior. Create custom analytics and understand how insights are generated. # What is Journium (/docs/angular/what-is-journium) import { RocketIcon } from 'lucide-react'; **Journium** turns raw telemetry into proactive, narrative insights — without charts, queries, or BI. Instead of asking humans to hunt through dashboards, Journium sits on top of your application's data and automatically detects meaningful behavioral changes, explains what happened, and surfaces insights in plain language. **Data exists. Awareness doesn't.** Journium flips that model. The Problem We're Solving [#the-problem-were-solving] Modern applications generate mountains of event data — every click, page view, transaction, and user interaction creates a data point. Yet despite this abundance of information, organizations struggle to extract clear, actionable insights in a timely manner. The Traditional Analytics Trap [#the-traditional-analytics-trap] The conventional approach to analytics follows a broken pattern: **Telemetry → Storage → Queries → Dashboards → Hope** Teams collect data, store it, build dashboards, and then... hope someone notices something important. This process demands: * **Manual exploration** — analysts must preprocess data, run queries, and interpret results * **Domain expertise** — understanding what to look for requires deep knowledge * **Significant time** — valuable knowledge often remains buried because generating insights traditionally requires significant manual effort * **Reactive discovery** — by the time an insight is found, it may be too late to act The result? **We have a data overload, but an insights shortage.** Busy product teams and executives rarely have the luxury to sift through dashboards or craft SQL queries on the fly. Important findings may be discovered too late or not at all. Why Dashboards Fall Short [#why-dashboards-fall-short] Static dashboards can show you *what* happened, but they rarely explain *why*. Even specialized BI tools struggle to surface the root causes behind metric movements. You're left with charts that require interpretation, correlation analysis, and often, a bit of guesswork. How Journium Flips the Narrative [#how-journium-flips-the-narrative] Journium reimagines analytics from the ground up. Instead of passive reporting tools, we've built an active system that acts like a data analyst working 24/7. The New Model: Telemetry → Meaning → Action [#the-new-model-telemetry--meaning--action] Journium follows a simple, powerful principle: **Telemetry → Meaning → Action** Not: Telemetry → Storage → Queries → Dashboards → Hope Your application doesn't need more dashboards. It needs a way to **speak up** when something meaningful changes. From Passive to Proactive [#from-passive-to-proactive] Traditional analytics asks: *"What do you want to know?"*\ Journium asks: *"What should you know?"* Instead of waiting for someone to query the data, Journium continuously monitors your application's behavior, detects significant changes, performs root-cause analysis, and delivers concise insights directly to you — in Slack, email, or wherever you need them. Think of it this way: Who has the time or interest to dig through charts if an AI can directly tell you *"users from segment X are churning due to feature Y issues, impacting conversion by Z%"* — with the data to back it up? Insights as Code: The Foundation [#insights-as-code-the-foundation] Journium introduces **"Insights as Code"** — a novel approach where insights are treated as a first-class, codified product, and an AI-driven engine transforms raw event data into human-ready insights. What This Means [#what-this-means] Just as Infrastructure as Code revolutionized how servers and networks are configured, Insights as Code brings software engineering rigor to analytics: * **Declarative specifications** — Define what you care about in code or configuration, not spreadsheets or Wiki pages * **Version-controlled** — Track changes, review insights, and maintain consistency across your team * **Automated generation** — Let AI do the heavy lifting of data crunching, pattern finding, and explanation generation * **Verifiable and transparent** — Every insight is backed by code and data, making it transparent and trustworthy The Power of AI-Driven Analysis [#the-power-of-ai-driven-analysis] Journium leverages Generative AI and large language models to automate insight generation. But this isn't about dumping data into an LLM and hoping for the best. Instead, we use a sophisticated, multi-step approach: 1. **Continuous monitoring** — Track behavioral patterns and detect significant changes 2. **Intelligent analysis** — Use AI agents to pose analytical questions, break them into sub-questions, query data, and synthesize findings 3. **Validation and guardrails** — Ensure insights are both interesting and trustworthy, with automatic validation of claims 4. **Concise delivery** — Generate short, factual takeaways (not long-winded reports) that get straight to the point This approach ensures insights are **concise, factual takeaways** rather than shallow observations or obvious outliers. The Vision: An Always-On System [#the-vision-an-always-on-system] Journium transforms analytics from a reactive process into an **always-on system** that actively drives growth. The vision is simple: 1. **Instrument once** — Integrate Journium's SDK into your application 2. **Define what matters** — Specify your goals and questions in configuration 3. **Receive insights automatically** — Get proactive, narrative insights delivered continuously The outcome? An analytics experience that feels almost magical: you integrate an SDK, define high-level goals in a config, and the system speaks to you with facts and explanations continuously — almost like a data-savvy colleague working around the clock. Yet under the hood, every insight is backed by code and data — transparent and verifiable. Why This Matters [#why-this-matters] In a world inundated with data, those who can harness AI to tell the story of the data will leap ahead. Journium eliminates the traditional divide between "data collection" and "insight generation," drastically reducing the time from question to answer and empowering teams to be truly data-driven without slogging through dashboards. The barrier to trying a new analysis becomes so low — just write a new tracker and let the AI do the rest. This unlocks creative uses of analytics that were previously too time-consuming or resource-intensive to pursue. **Stop looking for insights. Let your application tell you.** } href="/docs/angular" horizontal="true"> Get Journium integrated into your Angular app in under 5 minutes # API Methods (/docs/js/api-methods) API Reference [#api-reference] Complete reference for all Journium JavaScript SDK methods and functions. Initialization [#initialization] init(config) [#initconfig] Initializes and returns a new JourniumAnalytics instance. **Parameters:** | Parameter | Type | Required | Description | | ----------------------- | ---------------------- | -------- | -------------------------------------------------------------- | | `config` | `JourniumConfig` | Yes | Configuration object | | `config.publishableKey` | `string` | Yes | Your Journium publishable key | | `config.apiHost` | `string` | No | Custom API endpoint (default: `'https://events.journium.app'`) | | `config.options` | `JourniumLocalOptions` | No | Local configuration options | **Returns:** `JourniumAnalytics` - Analytics instance for tracking events **Example:** ```typescript import { init } from '@journium/js'; const journium = init({ publishableKey: 'pk_your_key_here', apiHost: 'https://events.journium.app', options: { debug: true, flushAt: 10, flushInterval: 5000 } }); ``` Event Tracking [#event-tracking] track(event, properties?) [#trackevent-properties] Tracks custom events with optional properties. **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | ---------------------------------- | | `event` | `string` | Yes | Event name to track | | `properties` | `Record` | No | Event properties (key-value pairs) | **Returns:** `void` **Examples:** **Basic event:** ```typescript journium.track('button_clicked'); ``` **Event with properties:** ```typescript journium.track('product_viewed', { product_id: 'prod_123', product_name: 'Running Shoes', price: 89.99, currency: 'USD', category: 'Footwear' }); ``` **E-commerce purchase:** ```typescript journium.track('purchase_completed', { order_id: 'order_789', revenue: 299.97, tax: 24.00, shipping: 10.00, items: [ { id: 'prod_123', name: 'Running Shoes', price: 89.99, quantity: 1 }, { id: 'prod_456', name: 'Sports Watch', price: 209.98, quantity: 1 } ] }); ``` **User action:** ```typescript journium.track('form_submitted', { form_name: 'contact_us', form_location: 'footer', fields_completed: 4, newsletter_signup: true }); ``` capturePageview(properties?) [#capturepageviewproperties] Manually captures pageview events. **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | ------------------- | | `properties` | `Record` | No | Pageview properties | **Returns:** `void` **Examples:** **Basic pageview:** ```typescript journium.capturePageview(); ``` **Pageview with custom properties:** ```typescript journium.capturePageview({ page_type: 'product', category: 'electronics', product_id: 'prod_123' }); ``` **SPA route change:** ```typescript router.on('routeChange', (route) => { journium.capturePageview({ route: route.path, previous_route: route.from, page_title: document.title }); }); ``` User Identity [#user-identity] identify(distinctId, attributes?) [#identifydistinctid-attributes] Identifies a user and associates future events with their identity. **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | --------------------------------------------- | | `distinctId` | `string` | Yes | Unique user identifier (email, user ID, etc.) | | `attributes` | `Record` | No | User attributes (name, email, plan, etc.) | **Returns:** `void` **Examples:** **Basic identification:** ```typescript journium.identify('user_12345'); ``` **With user attributes:** ```typescript journium.identify('user_12345', { email: 'john@example.com', name: 'John Doe', plan: 'premium', signup_date: '2024-01-15', total_purchases: 5, lifetime_value: 499.95 }); ``` **After login:** ```typescript function handleLogin(user) { journium.identify(user.id, { email: user.email, first_name: user.firstName, last_name: user.lastName, role: user.role, company: user.company }); } ``` **Update user attributes:** ```typescript // Identify again to update attributes journium.identify('user_12345', { plan: 'enterprise', // Updated plan last_login: new Date().toISOString() }); ``` reset() [#reset] Resets user identity, typically called on logout. Clears the current user ID and starts a new session. **Parameters:** None **Returns:** `void` **Example:** ```typescript function handleLogout() { // Track logout event journium.track('user_logged_out'); // Reset identity journium.reset(); // Redirect to login window.location.href = '/login'; } ``` ```typescript // In a logout button handler document.getElementById('logout-btn').addEventListener('click', () => { journium.reset(); // Perform logout logic }); ``` Autocapture Control [#autocapture-control] startAutocapture() [#startautocapture] Starts automatic event capture for clicks, form interactions, and pageviews. **Parameters:** None **Returns:** `void` **Note:** Autocapture behavior is configured during initialization via the `autocapture` option. **Example:** ```typescript const journium = init({ publishableKey: 'pk_...', options: { autocapture: { captureClicks: true, captureFormSubmits: true } } }); // Start capturing after user consent if (userHasConsented) { journium.startAutocapture(); } ``` stopAutocapture() [#stopautocapture] Stops automatic event capture. **Parameters:** None **Returns:** `void` **Example:** ```typescript // Stop capture when user opts out function handleOptOut() { journium.stopAutocapture(); journium.reset(); } ``` ```typescript // Temporarily disable during sensitive operations journium.stopAutocapture(); // Perform sensitive operation performPaymentProcessing(); journium.startAutocapture(); ``` Event Management [#event-management] flush() [#flush] Manually sends all queued events to the server immediately. **Parameters:** None **Returns:** `Promise` - Promise that resolves when events are sent **Examples:** **Basic flush:** ```typescript await journium.flush(); ``` **Before page unload:** ```typescript window.addEventListener('beforeunload', async (e) => { await journium.flush(); }); ``` **After critical action:** ```typescript async function handlePurchase(orderId) { journium.track('purchase_completed', { order_id: orderId }); // Ensure event is sent before redirect await journium.flush(); window.location.href = `/order-confirmation/${orderId}`; } ``` **With error handling:** ```typescript try { await journium.flush(); console.log('Events sent successfully'); } catch (error) { console.error('Failed to send events:', error); } ``` destroy() [#destroy] Cleans up the SDK, stops all tracking, flushes remaining events, and removes event listeners. **Parameters:** None **Returns:** `void` **Examples:** **On app unmount:** ```typescript // React useEffect(() => { return () => { journium.destroy(); }; }, []); ``` **Manual cleanup:** ```typescript function cleanupAnalytics() { journium.destroy(); console.log('Analytics cleaned up'); } ``` Configuration Management [#configuration-management] getEffectiveOptions() [#geteffectiveoptions] Returns the current effective configuration options (merged local and remote options). **Parameters:** None **Returns:** `JourniumLocalOptions` - Current effective configuration **Example:** ```typescript const options = journium.getEffectiveOptions(); console.log('Current configuration:', options); if (options.debug) { console.log('Debug mode is enabled'); } console.log(`Flush after ${options.flushAt} events`); console.log(`Flush every ${options.flushInterval}ms`); ``` onOptionsChange(callback) [#onoptionschangecallback] Register a callback to be notified when effective options change (e.g., when remote options are fetched). **Parameters:** | Parameter | Type | Required | Description | | ---------- | ----------------------------------------- | -------- | ------------------------------------ | | `callback` | `(options: JourniumLocalOptions) => void` | Yes | Function to call when options change | **Returns:** `() => void` - Unsubscribe function to stop listening to changes **Examples:** **Basic usage:** ```typescript const unsubscribe = journium.onOptionsChange((options) => { console.log('Options updated:', options); }); // Later, stop listening unsubscribe(); ``` **React with state:** ```typescript const [config, setConfig] = useState(null); useEffect(() => { const unsubscribe = journium.onOptionsChange((options) => { setConfig(options); console.log('Configuration loaded:', options); }); return () => unsubscribe(); }, []); ``` **Enable features based on remote config:** ```typescript journium.onOptionsChange((options) => { if (options.autocapture) { enableAutocaptureUI(); } if (options.debug) { showDebugPanel(); } }); ``` Complete Usage Example [#complete-usage-example] ```typescript import { init } from '@journium/js'; // 1. Initialize const journium = init({ publishableKey: 'pk_your_key', options: { debug: true, autocapture: { captureClicks: true, captureFormSubmits: true } } }); // 2. Start autocapture journium.startAutocapture(); // 3. Track custom events journium.track('app_loaded', { version: '1.0.0', platform: 'web' }); // 4. Identify user after login function onLogin(user) { journium.identify(user.id, { email: user.email, name: user.name, plan: user.plan }); journium.track('user_logged_in', { login_method: 'email' }); } // 5. Track user actions document.getElementById('buy-button').addEventListener('click', () => { journium.track('buy_button_clicked', { product_id: 'prod_123', location: 'homepage' }); }); // 6. Reset on logout function onLogout() { journium.track('user_logged_out'); journium.reset(); } // 7. Cleanup on page unload window.addEventListener('beforeunload', async () => { await journium.flush(); journium.destroy(); }); ``` Browser Console Methods [#browser-console-methods] For debugging in browser console: ```javascript // Check if SDK is loaded console.log(window.journium); // Get current configuration console.log(journium.getEffectiveOptions()); // Test tracking journium.track('console_test_event', { test: true }); // Force send events await journium.flush(); // View all methods console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(journium))); ``` Error Handling [#error-handling] The SDK handles errors gracefully, but you can add your own error handling: ```typescript // Track method calls are fire-and-forget (don't throw) journium.track('custom_event', { data: 'value' }); // Flush returns a promise you can catch journium.flush().catch(error => { console.error('Failed to flush events:', error); // Maybe retry or log to your error service }); // Listen for initialization failures journium.onOptionsChange((options) => { if (!options || Object.keys(options).length === 0) { console.warn('Failed to load remote configuration'); } }); ``` TypeScript Support [#typescript-support] All methods are fully typed. Import types for better IDE support: ```typescript import { init, type JourniumAnalytics, type JourniumConfig, type JourniumLocalOptions } from '@journium/js'; const config: JourniumConfig = { publishableKey: 'pk_...', options: { debug: true } }; const analytics: JourniumAnalytics = init(config); ``` Next Steps [#next-steps] Learn about all configuration options View complete type definitions See real-world implementation examples # CDN / Script Tag Usage (/docs/js/cdn-usage) import { ShopifyIcon } from '@/components/icons/shopify'; import { WordPressIcon } from '@/components/icons/wordpress'; Overview [#overview] Add Journium analytics to any website using a simple ` ``` Step 2: Track Events [#step-2-track-events] Once initialized, use the global `journium` object to track events: ```html ``` Static HTML Example [#static-html-example] ```html My Website ``` Next Steps [#next-steps] Explore all configuration options and settings Complete API method documentation Detailed Shopify store integration guide Complete WordPress site integration guide # Configuration Options (/docs/js/configuration) Configuration Options [#configuration-options] Configure every aspect of Journium to match your needs. Settings provided in the SDK take precedence over dashboard settings. Basic Configuration [#basic-configuration] Initialize Journium with your publishable key and optional configuration: ```ts title="index.ts" import { init } from '@journium/js'; const journium = init({ publishableKey: 'your-journium-publishable-key', apiHost: 'https://events.journium.app', // Optional: custom API endpoint options: { // Configuration options here } }); ``` Configuration Options Reference [#configuration-options-reference] Debug Mode [#debug-mode] Enable detailed logging for development and troubleshooting. ```typescript { debug: true // Default: false } ``` **When to use:** * ✅ Development environment * ✅ Debugging integration issues * ✅ Verifying events are tracked * ❌ Production (increases console output) **Example:** ```typescript const journium = init({ publishableKey: 'pk_test_...', options: { debug: process.env.NODE_ENV === 'development' } }); ``` Event Batching [#event-batching] Control how frequently events are sent to the server. Flush At [#flush-at] Number of events to accumulate before automatically sending to server. ```typescript { flushAt: 20 // Default: 20 } ``` **Recommendations:** * **High-traffic sites:** 50-100 (reduce server requests) * **Low-traffic sites:** 10-20 (faster event delivery) * **Real-time needs:** 1-5 (immediate sending) Flush Interval [#flush-interval] Time interval (milliseconds) between automatic flushes. ```typescript { flushInterval: 10000 // Default: 10000 (10 seconds) } ``` **Recommendations:** * **Standard sites:** 10000-30000ms * **Real-time dashboards:** 5000-10000ms * **Low-priority tracking:** 30000-60000ms **Example - Balanced Configuration:** ```typescript const journium = init({ publishableKey: 'pk_...', options: { flushAt: 20, // Send after 20 events flushInterval: 10000 // Or every 10 seconds } }); ``` Session Management [#session-management] Configure user session behavior and timeout. ```typescript { sessionTimeout: 1800000 // Default: 1800000 (30 minutes) } ``` **Common Values:** * **30 minutes:** `1800000` (standard) * **15 minutes:** `900000` (shorter sessions) * **1 hour:** `3600000` (longer sessions) * **24 hours:** `86400000` (persistent) **Use Cases:** * **E-commerce:** 30-60 minutes (shopping sessions) * **Content sites:** 30 minutes (reading sessions) * **SaaS apps:** 2-4 hours (work sessions) Automatic Pageview Tracking [#automatic-pageview-tracking] Automatically track pageview events on navigation. ```typescript { autoTrackPageviews: true // Default: true } ``` **When to disable:** * ❌ Single Page Applications with custom routing * ❌ When you want full control over pageview tracking * ✅ Keep enabled for standard websites **Example - Disable for SPA:** ```typescript const journium = init({ publishableKey: 'pk_...', options: { autoTrackPageviews: false // Manual tracking in SPA } }); // Then manually track pageviews router.on('routeChange', (route) => { journium.capturePageview({ route }); }); ``` Autocapture Configuration [#autocapture-configuration] Configure automatic capture of user interactions. Simple Enable/Disable [#simple-enabledisable] ```typescript { autocapture: true // or false } ``` Detailed Configuration [#detailed-configuration] ```typescript { autocapture: { captureClicks: true, // Track click events captureFormSubmits: true, // Track form submissions captureFormChanges: false, // Track form field changes captureTextSelection: false, // Track text selection ignoreClasses: ['no-track'], // CSS classes to ignore ignoreElements: ['script', 'style'], // HTML elements to ignore captureContentText: true // Capture element text content } } ``` **Configuration Examples:** **E-commerce Site:** ```typescript { autocapture: { captureClicks: true, captureFormSubmits: true, captureFormChanges: false, ignoreClasses: ['analytics-ignore', 'no-track'], ignoreElements: ['input[type="password"]', 'input[type="credit-card"]'] } } ``` **Blog/Content Site:** ```typescript { autocapture: { captureClicks: true, captureFormSubmits: true, captureTextSelection: true, // Track what users highlight ignoreClasses: ['ad', 'sponsored'] } } ``` **Privacy-Focused:** ```typescript { autocapture: { captureClicks: true, captureFormSubmits: false, // No form tracking captureFormChanges: false, captureContentText: false, // Don't capture text content ignoreElements: ['input', 'textarea'] // Ignore all inputs } } ``` API Host [#api-host] Custom API endpoint for self-hosted or regional deployments. ```typescript { apiHost: 'https://events.journium.app' // Default } ``` **Use Cases:** * **Self-hosted:** `https://analytics.yourcompany.com` * **Regional compliance:** `https://eu.journium.app` * **Development:** `http://localhost:3006` Complete Configuration Example [#complete-configuration-example] ```typescript import { init } from '@journium/js'; const journium = init({ publishableKey: process.env.JOURNIUM_KEY!, apiHost: 'https://events.journium.app', options: { // Development & Debugging debug: process.env.NODE_ENV === 'development', // Performance & Batching flushAt: 20, flushInterval: 10000, // Session Management sessionTimeout: 1800000, // 30 minutes // Automatic Tracking autoTrackPageviews: true, // Autocapture Configuration autocapture: { captureClicks: true, captureFormSubmits: true, captureFormChanges: false, captureTextSelection: false, ignoreClasses: ['no-track', 'analytics-ignore'], ignoreElements: [ 'input[type="password"]', 'input[type="credit-card"]', 'script', 'style' ], captureContentText: true } } }); // Start automatic capture journium.startAutocapture(); ``` Next Steps [#next-steps] Explore all available methods and functions View complete type definitions and interfaces Platform-specific configuration examples # How Journium Works (/docs/js/how-journium-works) Journium works by collecting [Events](/docs/react/concepts/events) from your application and then using AI to generate insights from those events. Users integrate the Journium SDK into their applications, which sends events to Journium's API where they are ingested and processed. Users then create [Insight Trackers](/docs/react/concepts/insight-trackers) that define the mechanics around how [Insights](/docs/react/concepts/insights) should be generated, and [Jobs](/docs/react/concepts/jobs) execute those trackers to produce insights. These insights are then available on the Journium dashboard for users to view and analyze. Journium Workflow [#journium-workflow] Event Collection [#event-collection] Event collection is the foundation of Journium's analytics pipeline. Users integrate the Journium SDK into their applications, which acts as a lightweight client library that captures user interactions and application events. When events occur in your application—such as user signups, purchases, feature usage, or errors—the SDK automatically sends these events to Journium's API endpoint. The API receives and ingests these events, storing them in a time-series database optimized for analytics queries. This continuous stream of event data provides the raw material that powers all subsequent analysis and insight generation. Tracker Definition [#tracker-definition] Trackers are declarative configurations that define what should be analyzed and how insights should be generated. Users create trackers through the Journium dashboard, specifying which events to monitor (or analyzing all events), setting custom instructions for the AI analysis, and configuring execution schedules. Each tracker acts like a continuous data analyst that monitors specific patterns in your event data. Trackers can be set to run automatically on a schedule (e.g., hourly, daily, weekly) or triggered manually for ad-hoc analysis. The tracker configuration includes parameters such as the maximum number of events to analyze, custom AI instructions that guide the analysis focus, and the specific event types to consider. This "Insights as Code" approach allows users to define what they want to know about their application without writing SQL queries or building dashboards. Job Execution [#job-execution] Job execution is the automated process that runs trackers and generates insights. When a tracker is scheduled to run or manually triggered, Journium creates a job that executes the tracker's analysis workflow. The job execution follows a multi-step pipeline: it first validates the tracker configuration and checks data availability, then queries the event database to retrieve the relevant events based on the tracker's configuration. The job then uses AI to analyze the event data, looking for patterns, trends, anomalies, and correlations. The AI engine processes the data according to the tracker's instructions, synthesizing findings into concise, natural language insights that are typically 1-3 sentences long and backed by verifiable data. Finally, the job stores the generated insights and updates the execution history, making them ready for display in the dashboard. Insights Display [#insights-display] Once insights are generated by job execution, they become available in the Journium dashboard for users to view and analyze. Insights are displayed in a feed format on the application instance's insights page, similar to a social media feed, where each insight appears as a card showing the analysis results, timestamp, and metadata. Users can interact with insights by liking them, adding comments for team collaboration, saving them for later reference, or sharing them with team members. The dashboard also provides features like pagination to browse through historical insights, filtering options, and the ability to see insight trends over time. This presentation format makes insights easily scannable and actionable, transforming raw event data into understandable narratives that help teams make data-driven decisions about their application. # JavaScript Quick Start (/docs/js) import { ShopifyIcon } from '@/components/icons/shopify'; import { WordPressIcon } from '@/components/icons/wordpress'; import { Settings, Code, FileCode } from 'lucide-react' Installation [#installation] We recommend one of the framework specific integrations for the best experience. Choose the installation method that best fits your project: **Ideal for websites without build tools.** ```html title="index.html" ``` Perfect for: * Static HTML websites * Shopify stores * WordPress sites * No-code platforms For detailed CDN usage including e-commerce tracking examples and advanced configurations, see the [CDN Usage Guide](/docs/js/cdn-usage). **Recommended for modern web applications with build tools.** ```bash title="Terminal" npm install @journium/js ``` Perfect for applications using: * Webpack, Vite, or other bundlers * TypeScript projects * Modern JavaScript frameworks
Set your Journium Publishable Key [#set-your-journium-publishable-key] 1. **Sign up for a Journium account** for free at [journium.app/signup](https://journium.app/signup) 2. **[Create an application](https://dashboard.journium.app/apps/new)** in your Journium dashboard 3. **Copy your Publishable Key** from the [Developers | API Keys](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/api-keys) section Dashboard URLs automatically navigate to your app - just click! Initialize Journium [#initialize-journium] Initialize the Journium SDK with your publishable key to start tracking events. ```html title="index.html" ``` ```ts title="index.ts" import { init } from '@journium/js'; const journium = init({ publishableKey: 'your-journium-publishable-key' }); ``` Track a Custom Event [#track-a-custom-event] Track user actions and business events with custom properties. ```html title="index.html" ``` ```ts title="index.ts" journium.track('button_clicked', { button_name: 'signup', page: 'homepage', user_type: 'visitor' }); ``` Identify a User [#identify-a-user] Identify users when they log in or sign up to connect their actions across sessions. ```html title="index.html" ``` ```ts title="index.ts" journium.identify('user_12345', { name: 'John Doe', email: 'john@example.com', plan: 'premium' }); ``` Reset User Identity [#reset-user-identity] Reset user identity when they log out to ensure privacy and accurate tracking. ```html title="index.html" ``` ```ts title="index.ts" journium.reset(); ``` Send Events to Journium [#send-events-to-journium] Navigate around your app to automatically send events to Journium. Then view your collected events at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events). **Success indicator:** You should see events appearing in your dashboard within a few seconds. Generate Your First Insight [#generate-your-first-insight] When you create an app in Journium, a default [Insight Tracker](/docs/react/concepts/insight_trackers) is automatically created. This tracker helps you test data ingestion and insight generation. 1. Go to your [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) page 2. Click the **`Analyze now`** button for the tracker titled **"User Engagement"** 3. Monitor the job status in [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs) 4. Wait for the job to complete (usually takes 1-2 minutes) 5. View your generated insights at [Dashboard | Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) Done [#done] **Congratulations!** You've successfully created your first insight with Journium!
Troubleshooting [#troubleshooting] * Verify your API key starts with `pk_` and is correctly set in your code * Check browser console for errors (F12 → Console) * Ensure you're interacting with your **local app** (not the dashboard) * Delete `node_modules` and reinstall dependencies: ```bash rm -rf node_modules && npm install ``` * Ensure Node.js version is 18+: ```bash node --version ``` Platform-Specific Guides [#platform-specific-guides] } href="/docs/js/shopify-integration"> Track product views, cart events, and purchases on your Shopify store } href="/docs/js/wordpress-integration"> Add analytics to your WordPress site and track blog engagement API Documentation [#api-documentation] }> Complete guide to all configuration options and settings }> > All methods, parameters, and usage examples }> > Complete type definitions for TypeScript projects What's next? [#whats-next] Learn how to send your own custom events to track user behavior. Create custom analytics and understand how insights are generated. # Shopify Integration (/docs/js/shopify-integration) Shopify Analytics Integration [#shopify-analytics-integration] Integrate Journium analytics with your Shopify store to track product views, cart events, purchases, and customer behavior. Installation [#installation] Step 1: Get Your Journium Publishable Key [#step-1-get-your-journium-publishable-key] 1. Create a Shopify application in your Journium Dashboard 2. Copy your Publishable Key from the API Keys section Step 2: Add Journium to Your Shopify Theme [#step-2-add-journium-to-your-shopify-theme] 1. **Log in to your Shopify Admin** 2. Go to **Online Store → Themes** 3. Click **Actions → Edit code** on your active theme 4. Open **Layout → theme.liquid** 5. **Add this code before ``**: ```html ``` 6. **Click Save** Step 3: Track E-commerce Events [#step-3-track-e-commerce-events] Add tracking for key shopping events by adding code to specific template files. Product View Tracking [#product-view-tracking] Track when customers view products to understand which products generate interest. **File:** `Templates → product.liquid` (or in your product template section) ```html ``` Collection View Tracking [#collection-view-tracking] Track collection page views to see which categories interest customers. **File:** `Templates → collection.liquid` ```html ``` Add to Cart Tracking [#add-to-cart-tracking] Track when products are added to cart - critical for conversion analysis. **Option 1: Using Theme Customization (Recommended)** 1. Go to **Online Store → Themes → Customize** 2. Open **Theme settings → Custom CSS** (or equivalent) 3. Use browser console to find your add-to-cart button selector 4. Add this to **Layout → theme.liquid** before ``: ```html ``` **Option 2: Using AJAX Cart Events** If your theme uses AJAX cart (most modern themes), add this: ```html ``` Checkout Started Tracking [#checkout-started-tracking] Track when customers begin the checkout process. **File:** `Layout → theme.liquid` (add before ``) ```html {% if template == 'cart' %} {% endif %} ``` Purchase Tracking [#purchase-tracking] Track completed purchases to measure conversion and revenue. **File:** Create a new snippet: `Snippets → journium-order-tracking.liquid` ```liquid {% if checkout.order_id %} {% endif %} ``` **Then include it in:** `Settings → Checkout → Order status page` (Additional scripts section) ```liquid {% render 'journium-order-tracking' %} ``` Search Tracking [#search-tracking] Track what customers are searching for in your store. **File:** `Templates → search.liquid` ```html ``` Advanced: Track Custom Events [#advanced-track-custom-events] Track Newsletter Signups [#track-newsletter-signups] ```html ``` Track Wishlist/Favorites (if your theme supports it) [#track-wishlistfavorites-if-your-theme-supports-it] ```html ``` Testing Your Integration [#testing-your-integration] 1. Test in Browser Console [#1-test-in-browser-console] Open your Shopify store and press F12 to open Developer Tools: ```javascript // Check if Journium is loaded console.log(window.journium); // Test tracking manually journium.track('test_event', { test: true }); // Check current configuration console.log(journium.getEffectiveOptions()); ``` 2. Verify in Journium Dashboard [#2-verify-in-journium-dashboard] 1. Go to your [Journium Dashboard](https://dashboard.journium.app) 2. Navigate to **Developers → Events** 3. You should see events appearing within seconds 3. Test Key Flows [#3-test-key-flows] * ✅ View a product page (check for "Product Viewed" event) * ✅ Add item to cart (check for "Product Added to Cart" event) * ✅ View cart page (check for "Checkout Started" when clicking checkout) * ✅ Complete a test purchase (check for "Order Completed" event) Shopify-Specific Considerations [#shopify-specific-considerations] 1. Liquid Variables [#1-liquid-variables] Shopify uses Liquid templating. Key variables you can use: * `{{ customer }}` - Current logged-in customer * `{{ product }}` - Current product (on product pages) * `{{ collection }}` - Current collection (on collection pages) * `{{ cart }}` - Shopping cart data * `{{ shop }}` - Store information * `{{ template }}` - Current template name 2. Theme Compatibility [#2-theme-compatibility] This integration works with all Shopify themes: * ✅ Dawn (Shopify's default theme) * ✅ Debut (legacy default) * ✅ Brooklyn, Narrative, Supply * ✅ Custom themes * ✅ Third-party premium themes 3. Shopify Plus Features [#3-shopify-plus-features] If you're on Shopify Plus, you can: * Add tracking to checkout.liquid for more detailed checkout tracking * Use Scripts API for advanced cart tracking * Create custom apps with more sophisticated integrations 4. GDPR Compliance [#4-gdpr-compliance] For European customers, ensure compliance: ```html ``` Performance Optimization [#performance-optimization] 1. Async Loading [#1-async-loading] The snippet loads asynchronously by default (`m.async=!0`), so it won't block page rendering. 2. Event Batching [#2-event-batching] Configure batching to reduce server requests: ```javascript journium.init({ publishableKey: 'YOUR_KEY', options: { flushAt: 20, // Send after 20 events flushInterval: 10000 // Or every 10 seconds } }); ``` 3. Minimize Liquid Processing [#3-minimize-liquid-processing] For high-traffic stores, consider caching product data client-side instead of using Liquid for every event. Troubleshooting [#troubleshooting] Events Not Showing Up? [#events-not-showing-up] 1. **Check browser console** for errors (F12 → Console) 2. **Verify publishable key** starts with `pk_` 3. **Check network tab** (F12 → Network) for requests to `events.journium.app` 4. **Disable ad blockers** temporarily for testing Liquid Errors? [#liquid-errors] 1. **Validate JSON syntax** - Liquid output must be valid JSON 2. **Use `| json` filter** for text values: `{{ product.title | json }}` 3. **Test in theme editor** preview before publishing Add to Cart Not Tracking? [#add-to-cart-not-tracking] 1. **Inspect your add to cart button** - selector may be different 2. **Check if using AJAX cart** - may need different implementation 3. **Look for JavaScript errors** in console Next Steps [#next-steps] Set up custom analytics for your Shopify store Understand your customer behavior data Customize tracking behavior and options # TypeScript Types (/docs/js/typescript-types) TypeScript Types [#typescript-types] Complete TypeScript type definitions for the Journium JavaScript SDK. All types are exported from `@journium/js` and `@journium/core`. Installation [#installation] The SDK includes full TypeScript definitions out of the box: ```bash npm install @journium/js # Types are included automatically - no @types package needed ``` Importing Types [#importing-types] ```typescript import { init, type JourniumAnalytics, type JourniumConfig, type JourniumLocalOptions, type AutocaptureOptions, type JourniumEvent, type PageviewProperties } from '@journium/js'; ``` Core Types [#core-types] JourniumConfig [#journiumconfig] Configuration object for initializing Journium. ```typescript interface JourniumConfig { /** * Your Journium publishable key (required) * Format: pk_[dev|staging|prod]_... */ publishableKey: string; /** * Custom API endpoint (optional) * Default: 'https://events.journium.app' */ apiHost?: string; /** * Local configuration options (optional) * These override remote dashboard settings */ options?: JourniumLocalOptions; } ``` **Example Usage:** ```typescript const config: JourniumConfig = { publishableKey: 'pk_live_abc123', apiHost: 'https://events.journium.app', options: { debug: false, flushAt: 20 } }; const journium = init(config); ``` JourniumLocalOptions [#journiumlocaloptions] Local configuration options that can be set on the client. ```typescript interface JourniumLocalOptions { /** * Enable debug logging to console * Default: false */ debug?: boolean; /** * Number of events before auto-flush * Default: 20 */ flushAt?: number; /** * Flush interval in milliseconds * Default: 10000 (10 seconds) */ flushInterval?: number; /** * Auto-capture configuration * Can be boolean or detailed options object * Default: true */ autocapture?: boolean | AutocaptureOptions; /** * Automatically track pageview events * Default: true */ autoTrackPageviews?: boolean; /** * Session timeout in milliseconds * Default: 1800000 (30 minutes) */ sessionTimeout?: number; /** * Additional dynamic properties */ [key: string]: unknown; } ``` **Example Usage:** ```typescript const options: JourniumLocalOptions = { debug: process.env.NODE_ENV === 'development', flushAt: 10, flushInterval: 5000, sessionTimeout: 3600000, // 1 hour autoTrackPageviews: true, autocapture: { captureClicks: true, captureFormSubmits: true } }; ``` AutocaptureOptions [#autocaptureoptions] Configuration for automatic event capture. ```typescript interface AutocaptureOptions { /** * Capture click events * Default: true */ captureClicks?: boolean; /** * Capture form submission events * Default: true */ captureFormSubmits?: boolean; /** * Capture form field change events * Default: false */ captureFormChanges?: boolean; /** * Capture text selection events * Default: false */ captureTextSelection?: boolean; /** * CSS classes to ignore during capture * Elements with these classes won't be tracked * Default: ['journium-ignore'] */ ignoreClasses?: string[]; /** * HTML elements to ignore during capture * Selector strings or tag names * Default: ['script', 'style', 'noscript'] */ ignoreElements?: string[]; /** * Capture element text content * Default: true */ captureContentText?: boolean; } ``` **Example Usage:** ```typescript const autocaptureConfig: AutocaptureOptions = { captureClicks: true, captureFormSubmits: true, captureFormChanges: false, captureTextSelection: false, ignoreClasses: ['no-track', 'analytics-ignore', 'gdpr-sensitive'], ignoreElements: [ 'input[type="password"]', 'input[type="credit-card"]', 'script', 'style' ], captureContentText: true }; const journium = init({ publishableKey: 'pk_...', options: { autocapture: autocaptureConfig } }); ``` JourniumAnalytics [#journiumanalytics] The main analytics class instance returned by `init()`. ```typescript class JourniumAnalytics { /** * Track a custom event */ track(event: string, properties?: Record): void; /** * Identify a user */ identify(distinctId: string, attributes?: Record): void; /** * Reset user identity (typically on logout) */ reset(): void; /** * Manually capture a pageview event */ capturePageview(properties?: Record): void; /** * Start automatic event capture */ startAutocapture(): void; /** * Stop automatic event capture */ stopAutocapture(): void; /** * Manually flush queued events */ flush(): Promise; /** * Get current effective options */ getEffectiveOptions(): JourniumLocalOptions; /** * Listen for options changes */ onOptionsChange( callback: (options: JourniumLocalOptions) => void ): () => void; /** * Cleanup and destroy instance */ destroy(): void; } ``` **Example Usage:** ```typescript import { init, type JourniumAnalytics } from '@journium/js'; const analytics: JourniumAnalytics = init({ publishableKey: 'pk_...' }); // All methods are fully typed analytics.track('custom_event', { prop: 'value' }); analytics.identify('user_123', { email: 'user@example.com' }); ``` Event Types [#event-types] JourniumEvent [#journiumevent] Internal event structure (for advanced use cases). ```typescript interface JourniumEvent { /** * Unique event identifier (UUIDv7) */ uuid: string; /** * Ingestion/publishable key */ ingestion_key: string; /** * Client timestamp (ISO 8601 format) */ client_timestamp: string; /** * Event name */ event: string; /** * Event properties (including system properties) */ properties: Record; } ``` PageviewProperties [#pageviewproperties] Properties automatically captured for pageview events. ```typescript interface PageviewProperties { /** * Full URL of the page */ $current_url?: string; /** * Hostname */ $host?: string; /** * URL pathname */ $pathname?: string; /** * URL search/query string */ $search?: string; /** * Page title */ $title?: string; /** * Referrer URL */ $referrer?: string; /** * Additional custom properties */ [key: string]: unknown; } ``` **Example Usage:** ```typescript const pageviewProps: PageviewProperties = { $current_url: 'https://example.com/product/123', $pathname: '/product/123', $title: 'Product Name - Store', category: 'electronics', product_id: '123' }; journium.capturePageview(pageviewProps); ``` Next Steps [#next-steps] See all methods with examples Learn about configuration options TypeScript types for React integration # What is Journium (/docs/js/what-is-journium) import { RocketIcon } from 'lucide-react'; **Journium** turns raw telemetry into proactive, narrative insights — without charts, queries, or BI. Instead of asking humans to hunt through dashboards, Journium sits on top of your application's data and automatically detects meaningful behavioral changes, explains what happened, and surfaces insights in plain language. **Data exists. Awareness doesn't.** Journium flips that model. The Problem We're Solving [#the-problem-were-solving] Modern applications generate mountains of event data — every click, page view, transaction, and user interaction creates a data point. Yet despite this abundance of information, organizations struggle to extract clear, actionable insights in a timely manner. The Traditional Analytics Trap [#the-traditional-analytics-trap] The conventional approach to analytics follows a broken pattern: **Telemetry → Storage → Queries → Dashboards → Hope** Teams collect data, store it, build dashboards, and then... hope someone notices something important. This process demands: * **Manual exploration** — analysts must preprocess data, run queries, and interpret results * **Domain expertise** — understanding what to look for requires deep knowledge * **Significant time** — valuable knowledge often remains buried because generating insights traditionally requires significant manual effort * **Reactive discovery** — by the time an insight is found, it may be too late to act The result? **We have a data overload, but an insights shortage.** Busy product teams and executives rarely have the luxury to sift through dashboards or craft SQL queries on the fly. Important findings may be discovered too late or not at all. Why Dashboards Fall Short [#why-dashboards-fall-short] Static dashboards can show you *what* happened, but they rarely explain *why*. Even specialized BI tools struggle to surface the root causes behind metric movements. You're left with charts that require interpretation, correlation analysis, and often, a bit of guesswork. How Journium Flips the Narrative [#how-journium-flips-the-narrative] Journium reimagines analytics from the ground up. Instead of passive reporting tools, we've built an active system that acts like a data analyst working 24/7. The New Model: Telemetry → Meaning → Action [#the-new-model-telemetry--meaning--action] Journium follows a simple, powerful principle: **Telemetry → Meaning → Action** Not: Telemetry → Storage → Queries → Dashboards → Hope Your application doesn't need more dashboards. It needs a way to **speak up** when something meaningful changes. From Passive to Proactive [#from-passive-to-proactive] Traditional analytics asks: *"What do you want to know?"*\ Journium asks: *"What should you know?"* Instead of waiting for someone to query the data, Journium continuously monitors your application's behavior, detects significant changes, performs root-cause analysis, and delivers concise insights directly to you — in Slack, email, or wherever you need them. Think of it this way: Who has the time or interest to dig through charts if an AI can directly tell you *"users from segment X are churning due to feature Y issues, impacting conversion by Z%"* — with the data to back it up? Insights as Code: The Foundation [#insights-as-code-the-foundation] Journium introduces **"Insights as Code"** — a novel approach where insights are treated as a first-class, codified product, and an AI-driven engine transforms raw event data into human-ready insights. What This Means [#what-this-means] Just as Infrastructure as Code revolutionized how servers and networks are configured, Insights as Code brings software engineering rigor to analytics: * **Declarative specifications** — Define what you care about in code or configuration, not spreadsheets or Wiki pages * **Version-controlled** — Track changes, review insights, and maintain consistency across your team * **Automated generation** — Let AI do the heavy lifting of data crunching, pattern finding, and explanation generation * **Verifiable and transparent** — Every insight is backed by code and data, making it transparent and trustworthy The Power of AI-Driven Analysis [#the-power-of-ai-driven-analysis] Journium leverages Generative AI and large language models to automate insight generation. But this isn't about dumping data into an LLM and hoping for the best. Instead, we use a sophisticated, multi-step approach: 1. **Continuous monitoring** — Track behavioral patterns and detect significant changes 2. **Intelligent analysis** — Use AI agents to pose analytical questions, break them into sub-questions, query data, and synthesize findings 3. **Validation and guardrails** — Ensure insights are both interesting and trustworthy, with automatic validation of claims 4. **Concise delivery** — Generate short, factual takeaways (not long-winded reports) that get straight to the point This approach ensures insights are **concise, factual takeaways** rather than shallow observations or obvious outliers. The Vision: An Always-On System [#the-vision-an-always-on-system] Journium transforms analytics from a reactive process into an **always-on system** that actively drives growth. The vision is simple: 1. **Instrument once** — Integrate Journium's SDK into your application 2. **Define what matters** — Specify your goals and questions in configuration 3. **Receive insights automatically** — Get proactive, narrative insights delivered continuously The outcome? An analytics experience that feels almost magical: you integrate an SDK, define high-level goals in a config, and the system speaks to you with facts and explanations continuously — almost like a data-savvy colleague working around the clock. Yet under the hood, every insight is backed by code and data — transparent and verifiable. Why This Matters [#why-this-matters] In a world inundated with data, those who can harness AI to tell the story of the data will leap ahead. Journium eliminates the traditional divide between "data collection" and "insight generation," drastically reducing the time from question to answer and empowering teams to be truly data-driven without slogging through dashboards. The barrier to trying a new analysis becomes so low — just write a new tracker and let the AI do the rest. This unlocks creative uses of analytics that were previously too time-consuming or resource-intensive to pursue. **Stop looking for insights. Let your application tell you.** } href="/docs/js" horizontal="true"> Get Journium integrated into your app in under 5 minutes # WordPress Integration (/docs/js/wordpress-integration) WordPress Analytics Integration [#wordpress-analytics-integration] Integrate Journium analytics with your WordPress site to track page views, user behavior, content engagement, and conversions. Installation [#installation] Method 1: Add to Theme (Recommended) [#method-1-add-to-theme-recommended] This method adds Journium tracking site-wide through your theme. Step 1: Get Your Journium Publishable Key [#step-1-get-your-journium-publishable-key] 1. Create a WordPress application in your Journium Dashboard 2. Copy your Publishable Key from the API Keys section Step 2: Add Tracking Code to functions.php [#step-2-add-tracking-code-to-functionsphp] 1. Go to **Appearance → Theme File Editor** 2. Select **functions.php** from the right sidebar 3. Add this code at the end of the file: ```php ``` 4. **Click "Update File"** Method 2: Add to Header/Footer (Alternative) [#method-2-add-to-headerfooter-alternative] For themes with custom header/footer areas: 1. Go to **Appearance → Customize → Additional CSS** or header/footer sections 2. Add the JavaScript snippet (without PHP tags) directly Method 3: Using a Code Snippet Plugin (Easiest) [#method-3-using-a-code-snippet-plugin-easiest] If you prefer not to edit theme files: 1. Install the **"Code Snippets"** or **"Insert Headers and Footers"** plugin 2. Add the JavaScript snippet to the header section 3. Save and activate Content Tracking [#content-tracking] Track Blog Post Views [#track-blog-post-views] Automatically track detailed blog post engagement: ```php name; }, get_the_category()); $tags = array_map(function($tag) { return $tag->name; }, get_the_tags() ?: []); ?> ``` Track Page Views [#track-page-views] Track static page views with metadata: ```php ``` Track Category/Archive Views [#track-categoryarchive-views] See which categories interest your readers: ```php ``` User Interaction Tracking [#user-interaction-tracking] Track Comment Submissions [#track-comment-submissions] Monitor engagement through comments: ```php ``` Track Form Submissions (Contact Form 7) [#track-form-submissions-contact-form-7] If you use Contact Form 7: ```php ``` Track Search Queries [#track-search-queries] See what visitors are searching for: ```php found_posts; ?> ``` E-commerce Tracking (WooCommerce) [#e-commerce-tracking-woocommerce] If you're running a WooCommerce store on WordPress: Track Product Views [#track-product-views] ```php ``` Track Add to Cart [#track-add-to-cart] ```php ``` Track Purchase Completion [#track-purchase-completion] ```php get_items() as $item) { $product = $item->get_product(); $items[] = array( 'product_id' => $item->get_product_id(), 'product_name' => $item->get_name(), 'quantity' => $item->get_quantity(), 'price' => $item->get_total(), 'sku' => $product ? $product->get_sku() : '' ); } ?> ``` Advanced Tracking [#advanced-tracking] Track Reading Progress (Blog Posts) [#track-reading-progress-blog-posts] See how far readers scroll through your content: ```javascript ``` Track Time on Page [#track-time-on-page] Measure engagement duration: ```javascript ``` Track External Link Clicks [#track-external-link-clicks] Monitor when users click links to external sites: ```javascript ``` Track Downloads [#track-downloads] Monitor file downloads: ```javascript ``` WordPress Plugin Compatibility [#wordpress-plugin-compatibility] Popular Plugins Tested [#popular-plugins-tested] Journium works seamlessly with: * ✅ **WooCommerce** - Full e-commerce tracking * ✅ **Contact Form 7** - Form submission tracking * ✅ **Yoast SEO** - No conflicts * ✅ **WPForms** - Form tracking compatible * ✅ **Elementor** - Page builder compatible * ✅ **Gutenberg** - Block editor compatible * ✅ **WPML** - Multilingual support * ✅ **Jetpack** - Works alongside Jetpack features Tracking with Popular Page Builders [#tracking-with-popular-page-builders] Elementor [#elementor] Add custom HTML widget with JavaScript tracking code. Divi [#divi] Use Code Module to add tracking snippets. Beaver Builder [#beaver-builder] Use HTML module for tracking code. Privacy & GDPR Compliance [#privacy--gdpr-compliance] Cookie Consent Integration [#cookie-consent-integration] Integrate with popular cookie consent plugins: ```php ``` GDPR Best Practices [#gdpr-best-practices] 1. **Update Privacy Policy** - Mention Journium analytics 2. **Cookie Banner** - Include Journium in your consent 3. **Data Retention** - Configure in Journium Dashboard 4. **User Rights** - Support data deletion requests Performance Optimization [#performance-optimization] 1. Conditional Loading [#1-conditional-loading] Only load on specific pages: ```php ``` 2. Async Loading [#2-async-loading] The snippet loads asynchronously by default - no impact on page load. 3. Event Batching [#3-event-batching] Configure to reduce requests: ```javascript journium.init({ publishableKey: 'YOUR_KEY', options: { flushAt: 20, // Send after 20 events flushInterval: 10000 // Or every 10 seconds } }); ``` Testing Your Integration [#testing-your-integration] 1. Enable Debug Mode [#1-enable-debug-mode] Temporarily enable debug logging: ```php journium.init({ publishableKey: 'YOUR_KEY', options: { debug: true // Set to false in production } }); ``` 2. Check Browser Console [#2-check-browser-console] Open Developer Tools (F12) and check: ```javascript // Verify Journium is loaded console.log(window.journium); // Test manual tracking journium.track('test_event', { test: true }); // View configuration console.log(journium.getEffectiveOptions()); ``` 3. Verify in Dashboard [#3-verify-in-dashboard] 1. Visit your WordPress site 2. Navigate to different pages 3. Check [Journium Dashboard → Developers → Events](https://dashboard.journium.app) 4. Events should appear within seconds Troubleshooting [#troubleshooting] Events Not Appearing? [#events-not-appearing] 1. **Clear WordPress cache** (if using caching plugin) 2. **Check browser console** for JavaScript errors 3. **Verify publishable key** is correct 4. **Disable ad blockers** for testing 5. **Check network requests** (F12 → Network tab) PHP Errors? [#php-errors] 1. **Check functions.php syntax** - missing semicolons, brackets 2. **Use child theme** to avoid losing changes on updates 3. **Enable WordPress debug mode** temporarily: ```php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); ``` Conflict with Other Scripts? [#conflict-with-other-scripts] 1. **Check console for errors** 2. **Try wrapping in DOMContentLoaded**: ```javascript document.addEventListener('DOMContentLoaded', function() { // Your tracking code }); ``` Best Practices [#best-practices] 1. Use Child Themes [#1-use-child-themes] Always add code to a child theme's functions.php to preserve changes during theme updates. 2. Version Control [#2-version-control] Keep track of your tracking code changes with version control. 3. Test Before Production [#3-test-before-production] Test tracking on a staging site before deploying to production. 4. Document Custom Events [#4-document-custom-events] Keep a list of custom events you're tracking for your team. 5. Regular Audits [#5-regular-audits] Periodically review tracked events and remove unused ones. WordPress Multisite [#wordpress-multisite] For WordPress multisite installations: ```php ``` Next Steps [#next-steps] Set up custom analytics for your WordPress site Understand your visitor behavior data Customize tracking behavior and options # React Configuration (/docs/react/configuration) React Configuration [#react-configuration] The Journium React SDK wraps the core [JavaScript SDK](/docs/js) and provides React-specific components and hooks. React-Specific Setup [#react-specific-setup] Provider Configuration [#provider-configuration] Wrap your app with `` to initialize Journium: ```tsx title="main.tsx" import React from 'react'; import { JourniumProvider } from '@journium/react'; import App from './App'; function Root() { return ( ); } export default Root; ``` ```tsx title="index.tsx" import React from 'react'; import ReactDOM from 'react-dom/client'; import { JourniumProvider } from '@journium/react'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')!); root.render( ); ``` Configuration Options [#configuration-options] The `config` prop accepts a `JourniumConfig` object with the following properties: * `publishableKey` (required): Your Journium publishable key * `apiHost` (optional): Custom API endpoint * `options` (optional): Configuration options object For detailed information about all available configuration options, see the [JavaScript SDK Configuration Guide](/docs/js/configuration). **Common options:** * `debug` - Enable debug logging * `flushAt` - Number of events before auto-flush * `flushInterval` - Flush interval in milliseconds * `sessionTimeout` - Session timeout duration * `autoTrackPageviews` - Automatically track page views * `autocapture` - Configure automatic event capture React Components [#react-components] [#journiumprovider] Provider component that initializes Journium analytics throughout your React application. **Props:** | Prop | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ---------------------- | | `config` | `JourniumConfig` | Yes | Configuration object | | `config.publishableKey` | `string` | Yes | Your publishable key | | `config.apiHost` | `string` | No | Custom API endpoint | | `config.options` | `JourniumLocalOptions` | No | Configuration options | | `children` | `ReactNode` | Yes | React children to wrap | **Example:** ```tsx ``` React Hooks [#react-hooks] The SDK provides React hooks for tracking events and managing user identity. See the [Hooks documentation](/docs/react/hooks) for detailed information: * [`useTrackEvent()`](/docs/react/hooks/use-track-event) - Track custom events * [`useIdentify()`](/docs/react/hooks/use-identify) - Identify users * [`useReset()`](/docs/react/hooks/use-reset) - Reset user identity * [`useTrackPageview()`](/docs/react/hooks) - Manual pageview tracking * [`useAutoTrackPageview()`](/docs/react/hooks) - Automatic pageview tracking * [`useAutocapture()`](/docs/react/hooks) - Control autocapture * [`useJournium()`](/docs/react/hooks) - Access analytics instance Context API [#context-api] Access the Journium context for advanced use cases: ```tsx import { useJournium } from '@journium/react'; function MyComponent() { const { analytics, config, effectiveOptions } = useJournium(); // Access analytics instance directly const options = analytics?.getEffectiveOptions(); return
Debug: {effectiveOptions?.debug ? 'On' : 'Off'}
; } ``` **Context Value:** ```typescript interface JourniumContextValue { analytics: JourniumAnalytics | null; config: JourniumConfig | null; effectiveOptions: JourniumLocalOptions | null; } ``` TypeScript Support [#typescript-support] The React SDK is fully typed. For complete type definitions, see the [JavaScript SDK TypeScript Types](/docs/js/typescript-types) documentation. All types are exported from `@journium/react`: ```typescript import { type JourniumConfig, type JourniumLocalOptions, type AutocaptureOptions } from '@journium/react'; ``` API Reference [#api-reference] For detailed API method reference (track, identify, reset, etc.), see the [JavaScript SDK API Methods](/docs/js/api-methods). The React hooks provide a convenient wrapper around these methods: | Hook | Underlying Method | | -------------------- | ----------------------------- | | `useTrackEvent()` | `analytics.track()` | | `useIdentify()` | `analytics.identify()` | | `useReset()` | `analytics.reset()` | | `useTrackPageview()` | `analytics.capturePageview()` | Next Steps [#next-steps] Learn about all available React hooks See all configuration options in detail Complete API method reference # How Journium Works (/docs/react/how-journium-works) Journium works by collecting [Events](/docs/react/concepts/events) from your application and then using AI to generate insights from those events. Users integrate the Journium SDK into their applications, which sends events to Journium's API where they are ingested and processed. Users then create [Insight Trackers](/docs/react/concepts/insight-trackers) that define the mechanics around how [Insights](/docs/react/concepts/insights) should be generated, and [Jobs](/docs/react/concepts/jobs) execute those trackers to produce insights. These insights are then available on the Journium dashboard for users to view and analyze. Journium Workflow [#journium-workflow] Event Collection [#event-collection] Event collection is the foundation of Journium's analytics pipeline. Users integrate the Journium SDK into their applications, which acts as a lightweight client library that captures user interactions and application events. When events occur in your application—such as user signups, purchases, feature usage, or errors—the SDK automatically sends these events to Journium's API endpoint. The API receives and ingests these events, storing them in a time-series database optimized for analytics queries. This continuous stream of event data provides the raw material that powers all subsequent analysis and insight generation. Tracker Definition [#tracker-definition] Trackers are declarative configurations that define what should be analyzed and how insights should be generated. Users create trackers through the Journium dashboard, specifying which events to monitor (or analyzing all events), setting custom instructions for the AI analysis, and configuring execution schedules. Each tracker acts like a continuous data analyst that monitors specific patterns in your event data. Trackers can be set to run automatically on a schedule (e.g., hourly, daily, weekly) or triggered manually for ad-hoc analysis. The tracker configuration includes parameters such as the maximum number of events to analyze, custom AI instructions that guide the analysis focus, and the specific event types to consider. This "Insights as Code" approach allows users to define what they want to know about their application without writing SQL queries or building dashboards. Job Execution [#job-execution] Job execution is the automated process that runs trackers and generates insights. When a tracker is scheduled to run or manually triggered, Journium creates a job that executes the tracker's analysis workflow. The job execution follows a multi-step pipeline: it first validates the tracker configuration and checks data availability, then queries the event database to retrieve the relevant events based on the tracker's configuration. The job then uses AI to analyze the event data, looking for patterns, trends, anomalies, and correlations. The AI engine processes the data according to the tracker's instructions, synthesizing findings into concise, natural language insights that are typically 1-3 sentences long and backed by verifiable data. Finally, the job stores the generated insights and updates the execution history, making them ready for display in the dashboard. Insights Display [#insights-display] Once insights are generated by job execution, they become available in the Journium dashboard for users to view and analyze. Insights are displayed in a feed format on the application instance's insights page, similar to a social media feed, where each insight appears as a card showing the analysis results, timestamp, and metadata. Users can interact with insights by liking them, adding comments for team collaboration, saving them for later reference, or sharing them with team members. The dashboard also provides features like pagination to browse through historical insights, filtering options, and the ability to see insight trends over time. This presentation format makes insights easily scannable and actionable, transforming raw event data into understandable narratives that help teams make data-driven decisions about their application. # React Quick Start (/docs/react) Setup [#setup] Set up Journium for your React application.
Install @journium/react [#install-journiumreact] The [Journium React SDK](/docs/react/hooks) gives you access to pre-built hooks and components to help you generate events in your React application and get insights from your data. Run the following command to install the SDK: npm pnpm yarn bun ```bash title="Terminal" npm i @journium/react ``` ```bash title="Terminal" pnpm add @journium/react ``` ```bash title="Terminal" yarn add @journium/react ``` ```bash title="Terminal" bun add @journium/react ``` Set your Journium Publishable Key [#set-your-journium-publishable-key] 1. **Sign up for a Journium account** for free at [journium.app/signup](https://journium.app/signup) 2. **[Create an application](https://dashboard.journium.app/apps/new)** in your Journium dashboard 3. **Copy your Publishable Key** from the [Developers | API Keys](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/api-keys) section Dashboard URLs automatically navigate to your app - just click! 4. **Create a `.env` file** in your project root: ```bash touch .env ``` 5. **Add your key** to the `.env` file: ```bash title=".env" VITE_JOURNIUM_PUBLISHABLE_KEY=your_publishable_key_here ``` ```bash title=".env" REACT_APP_JOURNIUM_PUBLISHABLE_KEY=your_publishable_key_here ``` 6. **Verify your setup** - check that the key is correctly saved: ```bash cat .env # Should show: VITE_JOURNIUM_PUBLISHABLE_KEY=pk_test_... ``` Development instances use `pk_test_` keys. Production keys start with `pk_live_`. Add to your app [#add-journiumprovider-to-your-app] The `` component provides session and user context to Journium's hooks. It's recommended to wrap your entire app at the entry point with `` to make analytics globally accessible throughout your application. ```tsx title="main.tsx" import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' // [!code ++:1] import { JourniumProvider } from '@journium/react'; import App from './App'; createRoot(document.getElementById('root')!).render( {/* [!code ++:5] */} {/* [!code ++:1] */} ); ``` ```tsx title="main.tsx" import React from 'react'; // [!code ++:1] import { JourniumProvider } from '@journium/react'; import App from './App'; function Root() { return ( // [!code ++:5] {/* [!code ++:1] */} ); } export default Root; ``` Run the Development Server [#run-the-development-server] Start your application: npm pnpm yarn bun ```bash title="Terminal" npm run dev ``` ```bash title="Terminal" pnpm run dev ``` ```bash title="Terminal" yarn dev ``` ```bash title="Terminal" bun run dev ``` **Using a custom port?** Add `-- --port 3000` to the dev command (for yarn, use `--port 3000` without the extra `--`). Verify Your Setup [#verify-your-setup] Open [http://localhost:5173](http://localhost:5173) (or your custom port) in your browser to see the application running. Send Events to Journium [#send-events-to-journium] Navigate around your app to automatically send events to Journium. Then view your collected events at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events). **Success indicator:** You should see events appearing in your dashboard within a few seconds. Generate Your First Insight [#generate-your-first-insight] When you create an app in Journium, a default [Insight Tracker](/docs/react/concepts/insight_trackers) is automatically created. This tracker helps you test data ingestion and insight generation. 1. Go to your [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) page 2. Click the **`Analyze now`** button for the tracker titled **"User Engagement"** 3. Monitor the job status in [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs) 4. Wait for the job to complete (usually takes 1-2 minutes) 5. View your generated insights at [Dashboard | Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) Done [#done] **Congratulations!** You've successfully created your first insight with Journium!
Troubleshooting [#troubleshooting] * Verify your API key starts with `pk_` and is correctly set in `.env` * Check browser console for errors (F12 → Console) * Ensure you're interacting with your **local app** (not the dashboard) * Restart the dev server after changing `.env` file * Delete `node_modules` and reinstall dependencies: ```bash rm -rf node_modules && npm install ``` * Ensure Node.js version is 18+: ```bash node --version ``` * Use a different port: ```bash npm run dev -- --port 3000 ``` * Or stop the process using the port: ```bash # macOS/Linux lsof -ti:5173 | xargs kill -9 ``` * Ensure the file is named exactly `.env` (not `.env.txt`) * Restart the development server after creating/modifying `.env` * Check file location: it must be in the project root, not in `src/` * For Vite projects, environment variables must be prefixed with `VITE_` What's next? [#whats-next] Learn how to send your own custom events to track user behavior. Create custom analytics and understand how insights are generated. # What is Journium (/docs/react/what-is-journium) import { RocketIcon } from 'lucide-react'; **Journium** turns raw telemetry into proactive, narrative insights — without charts, queries, or BI. Instead of asking humans to hunt through dashboards, Journium sits on top of your application's data and automatically detects meaningful behavioral changes, explains what happened, and surfaces insights in plain language. **Data exists. Awareness doesn't.** Journium flips that model. The Problem We're Solving [#the-problem-were-solving] Modern applications generate mountains of event data — every click, page view, transaction, and user interaction creates a data point. Yet despite this abundance of information, organizations struggle to extract clear, actionable insights in a timely manner. The Traditional Analytics Trap [#the-traditional-analytics-trap] The conventional approach to analytics follows a broken pattern: **Telemetry → Storage → Queries → Dashboards → Hope** Teams collect data, store it, build dashboards, and then... hope someone notices something important. This process demands: * **Manual exploration** — analysts must preprocess data, run queries, and interpret results * **Domain expertise** — understanding what to look for requires deep knowledge * **Significant time** — valuable knowledge often remains buried because generating insights traditionally requires significant manual effort * **Reactive discovery** — by the time an insight is found, it may be too late to act The result? **We have a data overload, but an insights shortage.** Busy product teams and executives rarely have the luxury to sift through dashboards or craft SQL queries on the fly. Important findings may be discovered too late or not at all. Why Dashboards Fall Short [#why-dashboards-fall-short] Static dashboards can show you *what* happened, but they rarely explain *why*. Even specialized BI tools struggle to surface the root causes behind metric movements. You're left with charts that require interpretation, correlation analysis, and often, a bit of guesswork. How Journium Flips the Narrative [#how-journium-flips-the-narrative] Journium reimagines analytics from the ground up. Instead of passive reporting tools, we've built an active system that acts like a data analyst working 24/7. The New Model: Telemetry → Meaning → Action [#the-new-model-telemetry--meaning--action] Journium follows a simple, powerful principle: **Telemetry → Meaning → Action** Not: Telemetry → Storage → Queries → Dashboards → Hope Your application doesn't need more dashboards. It needs a way to **speak up** when something meaningful changes. From Passive to Proactive [#from-passive-to-proactive] Traditional analytics asks: *"What do you want to know?"*\ Journium asks: *"What should you know?"* Instead of waiting for someone to query the data, Journium continuously monitors your application's behavior, detects significant changes, performs root-cause analysis, and delivers concise insights directly to you — in Slack, email, or wherever you need them. Think of it this way: Who has the time or interest to dig through charts if an AI can directly tell you *"users from segment X are churning due to feature Y issues, impacting conversion by Z%"* — with the data to back it up? Insights as Code: The Foundation [#insights-as-code-the-foundation] Journium introduces **"Insights as Code"** — a novel approach where insights are treated as a first-class, codified product, and an AI-driven engine transforms raw event data into human-ready insights. What This Means [#what-this-means] Just as Infrastructure as Code revolutionized how servers and networks are configured, Insights as Code brings software engineering rigor to analytics: * **Declarative specifications** — Define what you care about in code or configuration, not spreadsheets or Wiki pages * **Version-controlled** — Track changes, review insights, and maintain consistency across your team * **Automated generation** — Let AI do the heavy lifting of data crunching, pattern finding, and explanation generation * **Verifiable and transparent** — Every insight is backed by code and data, making it transparent and trustworthy The Power of AI-Driven Analysis [#the-power-of-ai-driven-analysis] Journium leverages Generative AI and large language models to automate insight generation. But this isn't about dumping data into an LLM and hoping for the best. Instead, we use a sophisticated, multi-step approach: 1. **Continuous monitoring** — Track behavioral patterns and detect significant changes 2. **Intelligent analysis** — Use AI agents to pose analytical questions, break them into sub-questions, query data, and synthesize findings 3. **Validation and guardrails** — Ensure insights are both interesting and trustworthy, with automatic validation of claims 4. **Concise delivery** — Generate short, factual takeaways (not long-winded reports) that get straight to the point This approach ensures insights are **concise, factual takeaways** rather than shallow observations or obvious outliers. The Vision: An Always-On System [#the-vision-an-always-on-system] Journium transforms analytics from a reactive process into an **always-on system** that actively drives growth. The vision is simple: 1. **Instrument once** — Integrate Journium's SDK into your application 2. **Define what matters** — Specify your goals and questions in configuration 3. **Receive insights automatically** — Get proactive, narrative insights delivered continuously The outcome? An analytics experience that feels almost magical: you integrate an SDK, define high-level goals in a config, and the system speaks to you with facts and explanations continuously — almost like a data-savvy colleague working around the clock. Yet under the hood, every insight is backed by code and data — transparent and verifiable. Why This Matters [#why-this-matters] In a world inundated with data, those who can harness AI to tell the story of the data will leap ahead. Journium eliminates the traditional divide between "data collection" and "insight generation," drastically reducing the time from question to answer and empowering teams to be truly data-driven without slogging through dashboards. The barrier to trying a new analysis becomes so low — just write a new tracker and let the AI do the rest. This unlocks creative uses of analytics that were previously too time-consuming or resource-intensive to pursue. **Stop looking for insights. Let your application tell you.** } href="/docs/react" horizontal="true"> Get Journium integrated into your app in under 5 minutes # Applications (/docs/concepts/application) What is an Application? [#what-is-an-application] Applications in Journium map directly to user applications where tracking is enabled. They have a one-to-one mapping with user apps. A Journium app is not a physical app in the traditional sense but a container to hold all configuration and settings related to tracking events, configuring insight trackers, and viewing app insights. How to Create Apps [#how-to-create-apps]
Create Application [#create-application] Go to your [Journium dashboard](https://dashboard.journium.app). If you have no apps you will land at the app listing page. Click on the **Create application** button, give a name for your application, and click **Create application**. Done [#done] When you create an app in Journium, it creates a default Development instance. This is for quick testing.
App Instances [#app-instances] An app can have two types of instances: **Development** and **Production**. These instances are independent of each other in terms of their configuration. The production instance is what you should track for production purposes. All features are available in both instances. You can create a production instance after you test adequately event generation, trackers, and insights in the Development instance. The instances can be switched in the instance selector in the dashboard. The API keys are different for the two instances. Development Instance [#development-instance] The Development instance is created by default when you create an app in Journium. It has lower usage quotas that are suitable for local testing and development purposes. Production Instance [#production-instance] The Production instance is what you should use for tracking in your production environment. You can create a production instance after you have adequately tested event generation, trackers, and insights in the Development instance. Configuration [#configuration] The configuration of an app is done in the [Journium dashboard](https://dashboard.journium.app). You can configure the app by clicking on the app in the dashboard and then clicking on the **Configure** tab in the sidebar. You can provide the configuration parameters directly on the SDK configuration. If not specified, the configuration that you supply in the dashboard will be used. The configuration in the SDK takes precedence over the configuration in the dashboard. The following settings are available. Event Capture settings [#event-capture-settings] This section allows you to configure the event capture settings for the app. Capture Clicks [#capture-clicks] When enabled, Journium will capture clicks on the app. Enable or disable the toggle switch to capture clicks on the app. Capture Form Submissions [#capture-form-submissions] Enable or disable the toggle switch to capture form submissions on the app. Capture Form Changes [#capture-form-changes] Enable or disable the toggle switch to capture form changes on the app. Capture Page Views [#capture-page-views] Journium can capture page views automatically. Enable or disable the toggle switch to capture page views automatically. Performance Settings [#performance-settings] Configure event batching parameters. Flush At [#flush-at] Configure the number of events to accumulate before flushing to the Journium API. Flush Interval (ms) [#flush-interval-ms] Configure the time interval in milliseconds between automatic flushes to the Journium API. # Events (/docs/concepts/events) What is an Event? [#what-is-an-event] An event in Journium is a single piece of telemetry data. Its the primary primitive that drives all the analytics and insights. When you use the Journium SDK, you are essentially sending events to Journium. Some events are auto-captured by the SDK, such as page views, clicks, form submissions, and errors, but you can control what you send to Journium. Event Structure [#event-structure] An event in Journium has the following structure: ```typescript { event: string; properties: Record; } ``` * `event`: The name of the event. * `properties`: A record of key-value pairs that you can use to add additional context to the event. Event Types [#event-types] There are two main types of events in Journium: * Custom Events * Auto-captured Events Custom Events [#custom-events] Custom Events are events that you manually send to Journium. You can send any event you want to Journium, and you can add any properties you want to the event. ```tsx title="app/your-path/page.tsx" import { useTrackEvent } from '@journium/nextjs'; function ProductPage() { const trackEvent = useTrackEvent(); const handlePurchase = () => { trackEvent('purchase_started', { product_id: 'prod_123', page: 'product_detail', value: 29.99 }); }; return ; } ``` Auto-captured Events [#auto-captured-events] Auto-captured Events are events that are automatically captured by the SDK. They can be enabled or disabled by configuring the SDK. See [Next.js Configuration](/docs/nextjs/configuration) or [Configuration](/docs/js/configuration) for more details. **Configuration Precedence** When you configure at the SDK level, it overrides the configuration in the Journium dashboard. The final derived configuration is the combination of the configuration in the Journium dashboard and the configuration in the SDK with the SDK configuration taking precedence. Viewing Events [#viewing-events] You can view events in the Journium dashboard. You can list them at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events) from your application instance page. Event Details [#event-details] You can view the details of an event by clicking on the event in the events listing. Event Simulator [#event-simulator] In your Development instance, you can test your event tracking by using the Event Simulator. It enables you to impersonate your app temporarily and send events on behalf of your app. This isuseful when you have not yet added custom eventsin your app via the SDK and want to test tracker execution based on events You can access it at [Developers | Event Simulation](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/simulation). # Concepts (/docs/concepts) Journium is built around the concept of an **Application**. An application in Journium mirrors your own application and is the starting point for all your telemetry. # Insights (/docs/concepts/insights) An Insight is the output of a [Insight Tracker](/docs/concepts/insight_trackers) run — a concise, AI-generated summary of your application's event data for a given time window. What is an Insight? [#what-is-an-insight] An Insight is a concise, AI-generated analysis of your application's event data, produced each time an [Insight Tracker](/docs/concepts/insight_trackers) runs. The LLM synthesises the structured query results into a natural-language summary using your configured `promptTemplate` — giving you an actionable, human-readable answer to the question your tracker is asking. Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page, ordered newest-first. What Each Insight Contains [#what-each-insight-contains] | Field | Description | | ------------------- | ---------------------------------------------- | | **Tracker** | The Insight Tracker that produced this insight | | **Generated at** | Timestamp of the job execution | | **Analysis window** | The time range analysed, e.g. "last 7 days" | | **Insight text** | The LLM-generated natural-language summary | How Insights are Generated [#how-insights-are-generated] Insights are produced by running a tracker — either on a schedule (`trigger.mode: automatic`) or on-demand (`trigger.mode: manual`). Each run goes through four steps: 1. **Query compilation** — Journium compiles the `analysis` config into analytical queries for the configured `window` 2. **Data retrieval** — queries run against your application's event data and return structured results 3. **Prompt rendering** — results are mapped to template variables and injected into `llm.promptTemplate` 4. **LLM synthesis** — the LLM generates the insight text, which is persisted and displayed See [Insight Trackers](/docs/concepts/insight_trackers) to learn how to configure the trackers that power your insights. Triggering an Insight [#triggering-an-insight] * **Scheduled** — trackers with `trigger.mode: automatic` run on the configured `schedule` (hourly, daily, weekly, or a cron expression). Each run produces a new insight. * **Manual** — trigger a run at any time from the tracker detail page in the dashboard, or via the API. Insight History [#insight-history] Every run appends a new insight to the history — previous insights are never overwritten. Deactivating or deleting a tracker does not remove past insights; the history is retained for reference. # Analysis Jobs (/docs/concepts/jobs) An Analysis Job in Journium is an execution instance of an [Insight Tracker](/docs/concepts/insight_trackers). Jobs are responsible for collecting data, analyzing events, and generating insights based on the tracker's configuration. Each job execution represents a single run of the tracker's workflow, from data collection to insight generation. What are Analysis Jobs? [#what-are-analysis-jobs] Jobs are the automated processes that execute Insight Trackers. When a tracker runs—either manually triggered or automatically scheduled—it creates a job that carries out the entire analysis workflow. Jobs handle the heavy lifting of: * Collecting relevant event data from your application * Reviewing execution history to understand context * Picking up and filtering relevant events based on the tracker configuration * Executing the tracker's instructions step by step * Generating insights when adequate data is available Think of a Job as a single execution of your Insight Tracker's analysis pipeline. Each job represents one attempt to analyze your data and generate insights. How Jobs Work [#how-jobs-work] Jobs execute the Insight Tracker workflow in a series of steps: **Configuration Loading**: The job picks up the configuration from its associated tracker, including event filters, instructions, and execution parameters **Data Collection**: The job collects relevant events from your application based on the tracker's event selection criteria **Execution History Review**: The job examines previous execution history to understand context and avoid redundant analysis **Event Processing**: Relevant events are filtered and prepared for analysis according to the tracker's configuration **Instruction Execution**: The tracker's instructions are executed step by step, analyzing the collected data **Insight Generation**: If adequate data is available, insights are generated and stored. If insufficient data exists, the job completes as a no-op without generating insights Job Execution Modes [#job-execution-modes] Jobs can be triggered in two ways: Manual Execution [#manual-execution] Jobs can be manually triggered for any tracker from the dashboard. This is useful for: * Testing tracker configurations during development * Running ad-hoc analysis on demand * Troubleshooting tracker behavior * Validating tracker setup before enabling scheduled execution To manually trigger a job, navigate to [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) and click the **`Analyze now`** button for the desired tracker. Automatic Execution [#automatic-execution] When a tracker is configured with **Scheduled** trigger mode, jobs are automatically created and executed according to the defined schedule (e.g., daily, weekly, hourly). This enables continuous monitoring and proactive insight generation without manual intervention. Viewing Jobs [#viewing-jobs] You can view all jobs for your application instance at [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs). Jobs List [#jobs-list] The jobs list provides an overview of all job executions, showing: {/* TODO: Add screenshot of jobs listing page from Journium dashboard */} * **Job Status**: Whether the job is pending, running, completed, or failed * **Tracker**: The Insight Tracker that triggered the job * **Execution Time**: When the job was created and executed * **Duration**: How long the job took to complete * **Result**: Whether insights were generated or if it was a no-op Job Details [#job-details] Clicking on a specific job opens the job details page, which provides comprehensive information about the execution: {/* TODO: Add screenshot of job details page from Journium dashboard */} The job details page shows: * **Execution Steps**: A breakdown of each step in the workflow execution * **Data Collected**: Information about the events and data processed during execution * **Job Output**: Detailed logs and output from each step of the execution * **Generated Insights**: Any insights that were created as a result of this job * **Error Information**: If the job failed, details about what went wrong Monitoring Job Execution [#monitoring-job-execution] Monitoring job output is particularly helpful during the process of developing trackers. The detailed execution logs help you: * **Troubleshoot Issues**: Identify where in the workflow a problem occurred * **Validate Configuration**: Verify that your tracker is collecting and processing the expected data * **Optimize Performance**: Understand which steps take the most time * **Debug Logic**: See exactly how your tracker's instructions are being executed By reviewing job details, you can iteratively refine your tracker configuration to ensure it's working as expected and generating meaningful insights. Job States [#job-states] Jobs progress through several states during execution: * **Pending**: The job has been created and is waiting to start execution * **Running**: The job is currently executing the tracker workflow * **Completed**: The job finished successfully (may or may not have generated insights) * **Failed**: The job encountered an error during execution * **No-op**: The job completed but didn't generate insights due to insufficient data No-op Jobs [#no-op-jobs] A job results in a no-op when there isn't adequate data available to execute the tracker's instructions meaningfully. This is a normal occurrence and doesn't indicate an error. Common reasons for no-op jobs include: * Not enough events matching the tracker's event filters * Insufficient data in the specified time window * Events don't contain the necessary data points for analysis No-op jobs are still valuable as they confirm your tracker is running correctly, even when there isn't enough data to generate insights yet. Best Practices [#best-practices] When working with Jobs: **Monitor During Development**: Regularly check job details when developing new trackers to ensure they're working as expected **Review Execution Logs**: Use job output to understand how your tracker processes data and identify potential improvements **Check Job History**: Review past job executions to understand patterns in data availability and insight generation **Use Manual Execution for Testing**: Trigger jobs manually when testing tracker configurations before enabling scheduled execution **Understand No-ops**: Don't be concerned about no-op jobs—they're normal when data is insufficient and indicate your tracker is running correctly **Job Monitoring**: The job details page provides real-time updates during execution, making it easy to monitor long-running jobs and troubleshoot issues as they occur. # Hooks Reference (/docs/hooks) Journium offers a comprehensive suite of hooks that expose low-level access to analytics, event tracking, and user identification. With Journium hooks, you can access and manage user data, handle event tracking, and generate a variety of insights from your data. Hooks [#hooks] * [`useIdentify()`](/docs/hooks/use-identify) * [`useTrackEvent()`](/docs/hooks/use-track-event) * [`useReset()`](/docs/hooks/use-reset) # useIdentify() (/docs/hooks/use-identify) Identify a User [#identify-a-user] The `useIdentify()` hook is used to identify a user when they log in or sign up. ```tsx title="pages/login.tsx" // [!code ++:1] import { useIdentify } from '@journium/nextjs'; function LoginPage() { // [!code ++:1] const identify = useIdentify(); const handleLogin = async (credentials) => { const user = await authenticateUser(credentials); // [!code ++:5] identify(user.id, { name: user.name, email: user.email, plan: user.plan }); }; return ( ); } ``` # useReset() (/docs/hooks/use-reset) Reset user identity [#reset-user-identity] The `useReset()` hook is used to reset user identity when they log out or when you want to clear the user's identity. ```tsx title="pages/logout.tsx" // [!code ++:1] import { useReset } from '@journium/nextjs'; function Header() { // [!code ++:1] const reset = useReset(); const handleLogout = async () => { await logoutUser(); // [!code ++:1] reset(); router.push('/'); }; return ; } ``` # useTrackEvent() (/docs/hooks/use-track-event) Track a custom event [#track-a-custom-event] The `useTrackEvent()` hook is used to track a custom event. You can track any event that you want to track in your application. ```tsx title="pages/dashboard.tsx" // [!code ++:1] import { useTrackEvent } from '@journium/nextjs'; function ProductPage() { // [!code ++:1] const trackEvent = useTrackEvent(); const handlePurchase = () => { // [!code ++:5] trackEvent('purchase_started', { product_id: 'prod_123', page: 'product_detail', value: 29.99 }); }; return ( ); } ``` # Tools (/docs/tools) Journium provides a set of developer focussed tools to develop with Journium faster and easier. # MCP Server (/docs/tools/mcp-server) The Journium MCP server enables AI agents to interact with Journium documentation, search for information, and access tools directly from your IDE. Built on the [Model Context Protocol](https://modelcontextprotocol.io), it provides seamless integration with AI-powered development environments. What is MCP? [#what-is-mcp] Model Context Protocol (MCP) is an open standard that allows AI agents to securely connect to external tools and data sources. The Journium MCP server exposes documentation search, page retrieval, and workflow prompts to compatible AI assistants. Server Endpoint [#server-endpoint] ``` https://mcp.journium.app/mcp ``` Available Tools [#available-tools] The MCP server provides the following capabilities: docs_search [#docs_search] Search through Journium documentation using semantic search. Returns relevant pages with excerpts showing matched content. docs_getPage [#docs_getpage] Retrieve the full content of a specific documentation page by its route or file path. Returns MDX content, plain text, and frontmatter metadata. docs_listRoutes [#docs_listroutes] Get a list of all available documentation routes. Optionally filter by prefix to explore specific sections. IDE Setup [#ide-setup] Cursor has built-in MCP support. Add the Journium MCP server to your configuration: **Option 1: Using Settings UI** 1. Open **Cursor Settings** 2. Navigate to **Tools & MCP** → **New MCP Server** 3. Add a new MCP server with these details: * **Name**: `mcp-journium` * **Type**: `http` * **URL**: `https://mcp.journium.app/mcp` **Option 2: Edit Configuration File** **macOS/Linux**: `~/.cursor/mcp.json`\ **Windows**: `%APPDATA%\Cursor\mcp.json` ```json title="mcp.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Cursor after saving the configuration. Add the server to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json title="claude_desktop_config.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Claude Desktop after saving the configuration. Cline supports MCP servers through VS Code settings: 1. Open VS Code Settings (`Cmd+,` / `Ctrl+,`) 2. Search for "Cline MCP" 3. Edit `cline.mcpServers` in `settings.json`: ```json title="settings.json" { "cline.mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Reload VS Code after saving the configuration. For other tools that support the Model Context Protocol, consult their documentation for adding HTTP-based MCP servers. **Server Configuration**: * **Type**: `HTTP` * **URL**: `https://mcp.journium.app/mcp` Most MCP-compatible tools accept configuration in a similar JSON format: ```json { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Refer to your tool's documentation for the specific configuration file location and format. Usage [#usage] Once configured, your AI agent can: * **Search documentation**: Ask questions about Journium features, APIs, or concepts * **Retrieve pages**: Get full documentation content for specific topics * **Explore structure**: Discover available documentation routes and sections The agent will automatically use the MCP server when answering Journium-related questions. Example Queries [#example-queries] With the MCP server configured, try asking your AI assistant: * "How do I set up a tracker in Journium?" * "Show me the Journium Next.js SDK documentation" * "How to integrate Journium in my Shopify store?" * "How to identify a user in Journium?" The agent will search the Journium documentation and provide accurate, up-to-date answers. Benefits [#benefits] **Always up-to-date**: The MCP server provides real-time access to the latest documentation—no stale training data. **Contextual assistance**: AI agents can search, retrieve, and reference official documentation while helping you build. **Seamless workflow**: Get answers without leaving your editor or switching to a browser. Privacy & Security [#privacy--security] **Read-only access**: The MCP server provides read-only access to public documentation. It cannot modify data or access private information. **No authentication required**: The server is publicly accessible and does not require API keys or authentication. **Secure connection**: All requests are made over HTTPS to ensure data integrity and privacy. Troubleshooting [#troubleshooting] Server Not Responding [#server-not-responding] If the MCP server isn't working: 1. Verify the URL is correct: `https://mcp.journium.app/mcp` 2. Check your internet connection 3. Restart your IDE or AI assistant 4. Ensure your MCP configuration file has valid JSON syntax AI Agent Not Using MCP Tools [#ai-agent-not-using-mcp-tools] If your AI agent isn't using the MCP server: 1. Confirm the server is properly configured in your tool's settings 2. Restart the application after adding the configuration 3. Try explicitly asking questions about Journium to trigger MCP usage 4. Check your tool's documentation for MCP-specific requirements Resources [#resources] * [Model Context Protocol Specification](https://modelcontextprotocol.io) * [GitHub Repository](https://github.com/journium/journium-docs/tree/main/apps/docs-mcp) * [Report Issues](https://github.com/journium/journium-docs/issues) # VS Code Extension (/docs/tools/vscode-extension) The Journium VS Code extension provides real-time validation, auto-completion, and tooling for insight tracker files. Works with VS Code and VS Code-compatible editors like Cursor. Installation [#installation] Recommended: Install from Your IDE [#recommended-install-from-your-ide] The quickest way to install is directly from your editor's Extensions view: 1. Open your editor (VS Code, Cursor, or other compatible IDE) 2. Go to the Extensions view (`Cmd+Shift+X` / `Ctrl+Shift+X`) 3. Search for "Journium" 4. Click Install Alternative: Direct Download [#alternative-direct-download] You can also install directly from these registries: * **VS Code users**: [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=Journium.journium) * **Cursor and other editors**: [Open VSX Registry](https://open-vsx.org/extension/Journium/journium) Many VS Code-compatible editors like Cursor use the Open VSX Registry as their extension source. Features [#features] Automatic Activation [#automatic-activation] The extension activates automatically when it detects tracker files in `.journium/trackers/` within your workspace. No manual configuration required. Real-time Schema Validation [#real-time-schema-validation] Get instant feedback as you write tracker YAML files. The extension validates all files under `.journium/trackers/` against the Journium insight tracker schema, catching errors before deployment. IntelliSense Support [#intellisense-support] Benefit from auto-completion, hover documentation, and inline schema hints while editing tracker files. Write trackers faster with contextual suggestions. Monorepo Ready [#monorepo-ready] Works seamlessly with monorepos and nested folder structures. The extension detects tracker files at any depth within your workspace. Getting Started [#getting-started] Once installed, the extension works automatically: 1. Create or open a workspace containing a `.journium/trackers/` folder 2. Add YAML files to define your trackers 3. Start editing—validation and IntelliSense activate automatically The extension activates when it detects files matching `**/.journium/trackers/**/*.yml` or `**/.journium/trackers/**/*.yaml`. How It Works [#how-it-works] The extension configures the [Red Hat YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) to validate tracker files using the Journium schema. When activated, it adds this configuration to your workspace settings: ```json { "yaml.schemas": { "https://journium.app/schemas/journium-insight-tracker.schema.json": [ "**/.journium/trackers/**/*.yml", "**/.journium/trackers/**/*.yaml" ] } } ``` This configuration: * Only affects files under `.journium/trackers/`—other YAML files remain unchanged * Persists across sessions * Can be committed to version control to share with your team Manual Configuration [#manual-configuration] If you need to manually trigger configuration, use the Command Palette: 1. Open Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) 2. Run: **Journium: Enable schema validation for this workspace** This is useful for setting up validation before creating tracker files. Requirements [#requirements] * VS Code 1.105.0 or higher (or compatible editor like Cursor) * Red Hat YAML extension (installed automatically as a dependency) Privacy & Performance [#privacy--performance] **Local validation**: All schema validation happens within your editor—no data is sent to external servers. **Zero overhead**: The extension uses VS Code's built-in file index to detect tracker folders without additional file system scans. Troubleshooting [#troubleshooting] Validation Not Working [#validation-not-working] If validation isn't working: 1. Verify your tracker files are under `.journium/trackers/` 2. Check that files have `.yml` or `.yaml` extensions 3. Run the manual configuration command from the Command Palette 4. Reload the window (`Developer: Reload Window`) Removing Validation [#removing-validation] To remove schema validation from your workspace: 1. Open `.vscode/settings.json` in your workspace 2. Remove the `yaml.schemas` entry for `journium-insight-tracker.schema.json` 3. Save the file Resources [#resources] * [GitHub Repository](https://github.com/journium/journium-vscode-extension) * [Report Issues](https://github.com/journium/journium-vscode-extension/issues) * [Tracker Schema Reference](/docs/concepts/insight_trackers/tracker_specification) # Applications (/docs/angular/concepts/application) What is an Application? [#what-is-an-application] Applications in Journium map directly to user applications where tracking is enabled. They have a one-to-one mapping with user apps. A Journium app is not a physical app in the traditional sense but a container to hold all configuration and settings related to tracking events, configuring insight trackers, and viewing app insights. How to Create Apps [#how-to-create-apps]
Create Application [#create-application] Go to your [Journium dashboard](https://dashboard.journium.app). If you have no apps you will land at the app listing page. Click on the **Create application** button, give a name for your application, and click **Create application**. Done [#done] When you create an app in Journium, it creates a default Development instance. This is for quick testing.
App Instances [#app-instances] An app can have two types of instances: **Development** and **Production**. These instances are independent of each other in terms of their configuration. The production instance is what you should track for production purposes. All features are available in both instances. You can create a production instance after you test adequately event generation, trackers, and insights in the Development instance. The instances can be switched in the instance selector in the dashboard. The API keys are different for the two instances. Development Instance [#development-instance] The Development instance is created by default when you create an app in Journium. It has lower usage quotas that are suitable for local testing and development purposes. Production Instance [#production-instance] The Production instance is what you should use for tracking in your production environment. You can create a production instance after you have adequately tested event generation, trackers, and insights in the Development instance. Configuration [#configuration] The configuration of an app is done in the [Journium dashboard](https://dashboard.journium.app). You can configure the app by clicking on the app in the dashboard and then clicking on the **Configure** tab in the sidebar. You can provide the configuration parameters directly on the SDK configuration. If not specified, the configuration that you supply in the dashboard will be used. The configuration in the SDK takes precedence over the configuration in the dashboard. The following settings are available. Event Capture settings [#event-capture-settings] This section allows you to configure the event capture settings for the app. Capture Clicks [#capture-clicks] When enabled, Journium will capture clicks on the app. Enable or disable the toggle switch to capture clicks on the app. Capture Form Submissions [#capture-form-submissions] Enable or disable the toggle switch to capture form submissions on the app. Capture Form Changes [#capture-form-changes] Enable or disable the toggle switch to capture form changes on the app. Capture Page Views [#capture-page-views] Journium can capture page views automatically. Enable or disable the toggle switch to capture page views automatically. Performance Settings [#performance-settings] Configure event batching parameters. Flush At [#flush-at] Configure the number of events to accumulate before flushing to the Journium API. Flush Interval (ms) [#flush-interval-ms] Configure the time interval in milliseconds between automatic flushes to the Journium API. # Events (/docs/angular/concepts/events) What is an Event? [#what-is-an-event] An event in Journium is a single piece of telemetry data. Its the primary primitive that drives all the analytics and insights. When you use the Journium SDK, you are essentially sending events to Journium. Some events are auto-captured by the SDK, such as page views, clicks, form submissions, and errors, but you can control what you send to Journium. Event Structure [#event-structure] An event in Journium has the following structure: ```typescript { event: string; properties: Record; } ``` * `event`: The name of the event. * `properties`: A record of key-value pairs that you can use to add additional context to the event. Event Types [#event-types] There are two main types of events in Journium: * Custom Events * Auto-captured Events Custom Events [#custom-events] Custom Events are events that you manually send to Journium. You can send any event you want to Journium, and you can add any properties you want to the event. ```typescript title="src/app/pages/home.component.ts" import { Component } from '@angular/core'; import { JourniumService } from '@journium/angular'; @Component({ selector: 'app-home', standalone: true, template: ``, }) export class HomeComponent { constructor(private journium: JourniumService) {} handleClick(): void { this.journium.track('purchase_completed', { product_id: 'prod-001', price: 29.99, currency: 'USD', }); } } ``` **Configuration Precedence** When you configure at the SDK level, it overrides the configuration in the Journium dashboard. The final derived configuration is the combination of the configuration in the Journium dashboard and the configuration in the SDK with the SDK configuration taking precedence. Viewing Events [#viewing-events] You can view events in the Journium dashboard. You can list them at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events) from your application instance page. Event Details [#event-details] You can view the details of an event by clicking on the event in the events listing. Event Simulator [#event-simulator] In your Development instance, you can test your event tracking by using the Event Simulator. It enables you to impersonate your app temporarily and send events on behalf of your app. This isuseful when you have not yet added custom eventsin your app via the SDK and want to test tracker execution based on events You can access it at [Developers | Event Simulation](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/simulation). # Insights (/docs/angular/concepts/insights) An Insight is the output of a [Insight Tracker](/docs/angular/concepts/insight_trackers) run — a concise, AI-generated summary of your application's event data for a given time window. What is an Insight? [#what-is-an-insight] An Insight is a concise, AI-generated analysis of your application's event data, produced each time an [Insight Tracker](/docs/concepts/insight_trackers) runs. The LLM synthesises the structured query results into a natural-language summary using your configured `promptTemplate` — giving you an actionable, human-readable answer to the question your tracker is asking. Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page, ordered newest-first. What Each Insight Contains [#what-each-insight-contains] | Field | Description | | ------------------- | ---------------------------------------------- | | **Tracker** | The Insight Tracker that produced this insight | | **Generated at** | Timestamp of the job execution | | **Analysis window** | The time range analysed, e.g. "last 7 days" | | **Insight text** | The LLM-generated natural-language summary | How Insights are Generated [#how-insights-are-generated] Insights are produced by running a tracker — either on a schedule (`trigger.mode: automatic`) or on-demand (`trigger.mode: manual`). Each run goes through four steps: 1. **Query compilation** — Journium compiles the `analysis` config into analytical queries for the configured `window` 2. **Data retrieval** — queries run against your application's event data and return structured results 3. **Prompt rendering** — results are mapped to template variables and injected into `llm.promptTemplate` 4. **LLM synthesis** — the LLM generates the insight text, which is persisted and displayed See [Insight Trackers](/docs/concepts/insight_trackers) to learn how to configure the trackers that power your insights. Triggering an Insight [#triggering-an-insight] * **Scheduled** — trackers with `trigger.mode: automatic` run on the configured `schedule` (hourly, daily, weekly, or a cron expression). Each run produces a new insight. * **Manual** — trigger a run at any time from the tracker detail page in the dashboard, or via the API. Insight History [#insight-history] Every run appends a new insight to the history — previous insights are never overwritten. Deactivating or deleting a tracker does not remove past insights; the history is retained for reference. # Analysis Jobs (/docs/angular/concepts/jobs) A Job in Journium is an execution instance of an [Insight Tracker](/docs/angular/concepts/insight_trackers). Jobs are responsible for collecting data, analyzing events, and generating insights based on the tracker's configuration. Each job execution represents a single run of the tracker's workflow, from data collection to insight generation. What are Analysis Jobs? [#what-are-analysis-jobs] Jobs are the automated processes that execute Insight Trackers. When a tracker runs—either manually triggered or automatically scheduled—it creates a job that carries out the entire analysis workflow. Jobs handle the heavy lifting of: * Collecting relevant event data from your application * Reviewing execution history to understand context * Picking up and filtering relevant events based on the tracker configuration * Executing the tracker's instructions step by step * Generating insights when adequate data is available Think of a Job as a single execution of your Insight Tracker's analysis pipeline. Each job represents one attempt to analyze your data and generate insights. How Jobs Work [#how-jobs-work] Jobs execute the Insight Tracker workflow in a series of steps: **Configuration Loading**: The job picks up the configuration from its associated tracker, including event filters, instructions, and execution parameters **Data Collection**: The job collects relevant events from your application based on the tracker's event selection criteria **Execution History Review**: The job examines previous execution history to understand context and avoid redundant analysis **Event Processing**: Relevant events are filtered and prepared for analysis according to the tracker's configuration **Instruction Execution**: The tracker's instructions are executed step by step, analyzing the collected data **Insight Generation**: If adequate data is available, insights are generated and stored. If insufficient data exists, the job completes as a no-op without generating insights Job Execution Modes [#job-execution-modes] Jobs can be triggered in two ways: Manual Execution [#manual-execution] Jobs can be manually triggered for any tracker from the dashboard. This is useful for: * Testing tracker configurations during development * Running ad-hoc analysis on demand * Troubleshooting tracker behavior * Validating tracker setup before enabling scheduled execution To manually trigger a job, navigate to [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) and click the **`Analyze now`** button for the desired tracker. Automatic Execution [#automatic-execution] When a tracker is configured with **Scheduled** trigger mode, jobs are automatically created and executed according to the defined schedule (e.g., daily, weekly, hourly). This enables continuous monitoring and proactive insight generation without manual intervention. Viewing Jobs [#viewing-jobs] You can view all jobs for your application instance at [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs). Jobs List [#jobs-list] The jobs list provides an overview of all job executions, showing: {/* TODO: Add screenshot of jobs listing page from Journium dashboard */} * **Job Status**: Whether the job is pending, running, completed, or failed * **Tracker**: The Insight Tracker that triggered the job * **Execution Time**: When the job was created and executed * **Duration**: How long the job took to complete * **Result**: Whether insights were generated or if it was a no-op Job Details [#job-details] Clicking on a specific job opens the job details page, which provides comprehensive information about the execution: {/* TODO: Add screenshot of job details page from Journium dashboard */} The job details page shows: * **Execution Steps**: A breakdown of each step in the workflow execution * **Data Collected**: Information about the events and data processed during execution * **Job Output**: Detailed logs and output from each step of the execution * **Generated Insights**: Any insights that were created as a result of this job * **Error Information**: If the job failed, details about what went wrong Monitoring Job Execution [#monitoring-job-execution] Monitoring job output is particularly helpful during the process of developing trackers. The detailed execution logs help you: * **Troubleshoot Issues**: Identify where in the workflow a problem occurred * **Validate Configuration**: Verify that your tracker is collecting and processing the expected data * **Optimize Performance**: Understand which steps take the most time * **Debug Logic**: See exactly how your tracker's instructions are being executed By reviewing job details, you can iteratively refine your tracker configuration to ensure it's working as expected and generating meaningful insights. Job States [#job-states] Jobs progress through several states during execution: * **Pending**: The job has been created and is waiting to start execution * **Running**: The job is currently executing the tracker workflow * **Completed**: The job finished successfully (may or may not have generated insights) * **Failed**: The job encountered an error during execution * **No-op**: The job completed but didn't generate insights due to insufficient data No-op Jobs [#no-op-jobs] A job results in a no-op when there isn't adequate data available to execute the tracker's instructions meaningfully. This is a normal occurrence and doesn't indicate an error. Common reasons for no-op jobs include: * Not enough events matching the tracker's event filters * Insufficient data in the specified time window * Events don't contain the necessary data points for analysis No-op jobs are still valuable as they confirm your tracker is running correctly, even when there isn't enough data to generate insights yet. Best Practices [#best-practices] When working with Jobs: **Monitor During Development**: Regularly check job details when developing new trackers to ensure they're working as expected **Review Execution Logs**: Use job output to understand how your tracker processes data and identify potential improvements **Check Job History**: Review past job executions to understand patterns in data availability and insight generation **Use Manual Execution for Testing**: Trigger jobs manually when testing tracker configurations before enabling scheduled execution **Understand No-ops**: Don't be concerned about no-op jobs—they're normal when data is insufficient and indicate your tracker is running correctly **Job Monitoring**: The job details page provides real-time updates during execution, making it easy to monitor long-running jobs and troubleshoot issues as they occur. # Angular Services (/docs/angular/services) Angular Services [#angular-services] The Journium Angular SDK provides a single injectable service, `JourniumService`, which wraps the core JavaScript SDK and exposes all analytics methods via Angular's dependency injection system. Available Services [#available-services] | Service | Description | | ------------------------------------------------------------ | ----------------------------------------------------------------------- | | [`JourniumService`](/docs/angular/services/journium-service) | Main analytics service — track events, identify users, manage pageviews | How to Use [#how-to-use] Inject `JourniumService` in any standalone component, NgModule-based component, or service after calling `provideJournium()` or importing `JourniumModule.forRoot()`: ```typescript import { Component } from '@angular/core'; import { JourniumService } from '@journium/angular'; @Component({ selector: 'app-example', standalone: true, template: ``, }) export class ExampleComponent { constructor(private journium: JourniumService) {} track(): void { this.journium.track('example_event', { source: 'example' }); } } ``` Cleanup [#cleanup] `JourniumService` implements Angular's `OnDestroy` interface. When the service is destroyed (on application teardown), it automatically calls `analytics.destroy()` to flush pending events and clean up resources. You do not need to call `destroy()` manually. Complete API reference for JourniumService # JourniumService (/docs/angular/services/journium-service) JourniumService [#journiumservice] `JourniumService` is the main Angular service provided by `@journium/angular`. It wraps the core JavaScript SDK and exposes all analytics methods for use throughout your Angular application. Setup [#setup] Ensure `JourniumService` is available by calling `provideJournium()` (standalone) or importing `JourniumModule.forRoot()` (NgModule) at application root: `JourniumService` does **not** have an `@Injectable()` decorator and cannot be added to any `providers` array directly. It is only available when registered via `provideJournium()` or `JourniumModule.forRoot()`. Attempting to provide it manually will cause a runtime DI error. ```typescript title="src/main.ts (standalone)" import { provideJournium } from '@journium/angular'; bootstrapApplication(AppComponent, { providers: [ provideJournium({ publishableKey: 'pk_...' }), ], }); ``` Then inject the service in any component or service: ```typescript import { JourniumService } from '@journium/angular'; @Component({ ... }) export class MyComponent { constructor(private journium: JourniumService) {} } ``` Methods [#methods] track(event, properties?) [#trackevent-properties] Track a custom event with optional properties. ```typescript this.journium.track('button_clicked', { button_text: 'Sign Up', page: '/home', plan: 'pro', }); ``` **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | ----------------------------------------- | | `event` | `string` | Yes | Event name (e.g., `'purchase_completed'`) | | `properties` | `Record` | No | Key-value event properties | *** identify(distinctId, attributes?) [#identifydistinctid-attributes] Associate subsequent events with a specific user. Call this after a user logs in. ```typescript this.journium.identify('user-123', { name: 'Alice Smith', email: 'alice@example.com', plan: 'enterprise', }); ``` **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | ----------------------------------------- | | `distinctId` | `string` | Yes | Unique identifier for the user | | `attributes` | `Record` | No | User attributes (name, email, plan, etc.) | *** reset() [#reset] Clear the current user identity. Call this when a user logs out. ```typescript this.journium.reset(); ``` *** capturePageview(properties?) [#capturepageviewproperties] Manually capture a pageview event. When using `withJourniumRouter()`, pageviews are captured automatically on each `NavigationEnd` event. Use this for manual tracking. ```typescript this.journium.capturePageview({ page: '/checkout', step: 'payment', }); ``` **Parameters:** | Parameter | Type | Required | Description | | ------------ | ------------------------- | -------- | ------------------------------ | | `properties` | `Record` | No | Additional pageview properties | *** startAutocapture() [#startautocapture] Start automatic event capture (clicks, form submits, etc.). Usually controlled via configuration rather than calling directly. ```typescript this.journium.startAutocapture(); ``` *** stopAutocapture() [#stopautocapture] Stop automatic event capture. ```typescript this.journium.stopAutocapture(); ``` *** getEffectiveOptions() [#geteffectiveoptions] Returns the currently active configuration options (merged from local and remote config). ```typescript const options = this.journium.getEffectiveOptions(); console.log(options.debug); // true/false ``` **Returns:** `JourniumLocalOptions` *** Lifecycle: ngOnDestroy() [#lifecycle-ngondestroy] `JourniumService` implements `OnDestroy`. On application teardown, it automatically flushes pending events and destroys the analytics instance. No manual cleanup is required. Example: Component with full lifecycle [#example-component-with-full-lifecycle] ```typescript import { Component, OnInit, OnDestroy } from '@angular/core'; import { JourniumService } from '@journium/angular'; @Component({ selector: 'app-checkout', standalone: true, template: `
`, }) export class CheckoutComponent implements OnInit, OnDestroy { constructor(private journium: JourniumService) {} ngOnInit(): void { this.journium.track('checkout_page_viewed'); } addItem(): void { this.journium.track('item_added_to_cart', { product_id: 'prod-001', price: 29.99, }); } checkout(): void { this.journium.track('checkout_started', { cart_total: 29.99, item_count: 1, }); } ngOnDestroy(): void { // No cleanup needed — JourniumService handles this automatically } } ``` Next Steps [#next-steps] Learn about all configuration options Best practices for custom event tracking # MCP Server (/docs/angular/tools/mcp-server) The Journium MCP server enables AI agents to interact with Journium documentation, search for information, and access tools directly from your IDE. Built on the [Model Context Protocol](https://modelcontextprotocol.io), it provides seamless integration with AI-powered development environments. What is MCP? [#what-is-mcp] Model Context Protocol (MCP) is an open standard that allows AI agents to securely connect to external tools and data sources. The Journium MCP server exposes documentation search, page retrieval, and workflow prompts to compatible AI assistants. Server Endpoint [#server-endpoint] ``` https://mcp.journium.app/mcp ``` Available Tools [#available-tools] The MCP server provides the following capabilities: docs_search [#docs_search] Search through Journium documentation using semantic search. Returns relevant pages with excerpts showing matched content. docs_getPage [#docs_getpage] Retrieve the full content of a specific documentation page by its route or file path. Returns MDX content, plain text, and frontmatter metadata. docs_listRoutes [#docs_listroutes] Get a list of all available documentation routes. Optionally filter by prefix to explore specific sections. IDE Setup [#ide-setup] Cursor has built-in MCP support. Add the Journium MCP server to your configuration: **Option 1: Using Settings UI** 1. Open **Cursor Settings** 2. Navigate to **Tools & MCP** → **New MCP Server** 3. Add a new MCP server with these details: * **Name**: `mcp-journium` * **Type**: `http` * **URL**: `https://mcp.journium.app/mcp` **Option 2: Edit Configuration File** **macOS/Linux**: `~/.cursor/mcp.json`\ **Windows**: `%APPDATA%\Cursor\mcp.json` ```json title="mcp.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Cursor after saving the configuration. Add the server to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json title="claude_desktop_config.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Claude Desktop after saving the configuration. Cline supports MCP servers through VS Code settings: 1. Open VS Code Settings (`Cmd+,` / `Ctrl+,`) 2. Search for "Cline MCP" 3. Edit `cline.mcpServers` in `settings.json`: ```json title="settings.json" { "cline.mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Reload VS Code after saving the configuration. For other tools that support the Model Context Protocol, consult their documentation for adding HTTP-based MCP servers. **Server Configuration**: * **Type**: `HTTP` * **URL**: `https://mcp.journium.app/mcp` Most MCP-compatible tools accept configuration in a similar JSON format: ```json { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Refer to your tool's documentation for the specific configuration file location and format. Usage [#usage] Once configured, your AI agent can: * **Search documentation**: Ask questions about Journium features, APIs, or concepts * **Retrieve pages**: Get full documentation content for specific topics * **Explore structure**: Discover available documentation routes and sections The agent will automatically use the MCP server when answering Journium-related questions. Example Queries [#example-queries] With the MCP server configured, try asking your AI assistant: * "How do I set up a tracker in Journium?" * "Show me the Journium Next.js SDK documentation" * "How to integrate Journium in my Shopify store?" * "How to identify a user in Journium?" The agent will search the Journium documentation and provide accurate, up-to-date answers. Benefits [#benefits] **Always up-to-date**: The MCP server provides real-time access to the latest documentation—no stale training data. **Contextual assistance**: AI agents can search, retrieve, and reference official documentation while helping you build. **Seamless workflow**: Get answers without leaving your editor or switching to a browser. Privacy & Security [#privacy--security] **Read-only access**: The MCP server provides read-only access to public documentation. It cannot modify data or access private information. **No authentication required**: The server is publicly accessible and does not require API keys or authentication. **Secure connection**: All requests are made over HTTPS to ensure data integrity and privacy. Troubleshooting [#troubleshooting] Server Not Responding [#server-not-responding] If the MCP server isn't working: 1. Verify the URL is correct: `https://mcp.journium.app/mcp` 2. Check your internet connection 3. Restart your IDE or AI assistant 4. Ensure your MCP configuration file has valid JSON syntax AI Agent Not Using MCP Tools [#ai-agent-not-using-mcp-tools] If your AI agent isn't using the MCP server: 1. Confirm the server is properly configured in your tool's settings 2. Restart the application after adding the configuration 3. Try explicitly asking questions about Journium to trigger MCP usage 4. Check your tool's documentation for MCP-specific requirements Resources [#resources] * [Model Context Protocol Specification](https://modelcontextprotocol.io) * [GitHub Repository](https://github.com/journium/journium-docs/tree/main/apps/docs-mcp) * [Report Issues](https://github.com/journium/journium-docs/issues) # VS Code Extension (/docs/angular/tools/vscode-extension) The Journium VS Code extension provides real-time validation, auto-completion, and tooling for insight tracker files. Works with VS Code and VS Code-compatible editors like Cursor. Installation [#installation] Recommended: Install from Your IDE [#recommended-install-from-your-ide] The quickest way to install is directly from your editor's Extensions view: 1. Open your editor (VS Code, Cursor, or other compatible IDE) 2. Go to the Extensions view (`Cmd+Shift+X` / `Ctrl+Shift+X`) 3. Search for "Journium" 4. Click Install Alternative: Direct Download [#alternative-direct-download] You can also install directly from these registries: * **VS Code users**: [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=Journium.journium) * **Cursor and other editors**: [Open VSX Registry](https://open-vsx.org/extension/Journium/journium) Many VS Code-compatible editors like Cursor use the Open VSX Registry as their extension source. Features [#features] Automatic Activation [#automatic-activation] The extension activates automatically when it detects tracker files in `.journium/trackers/` within your workspace. No manual configuration required. Real-time Schema Validation [#real-time-schema-validation] Get instant feedback as you write tracker YAML files. The extension validates all files under `.journium/trackers/` against the Journium insight tracker schema, catching errors before deployment. IntelliSense Support [#intellisense-support] Benefit from auto-completion, hover documentation, and inline schema hints while editing tracker files. Write trackers faster with contextual suggestions. Monorepo Ready [#monorepo-ready] Works seamlessly with monorepos and nested folder structures. The extension detects tracker files at any depth within your workspace. Getting Started [#getting-started] Once installed, the extension works automatically: 1. Create or open a workspace containing a `.journium/trackers/` folder 2. Add YAML files to define your trackers 3. Start editing—validation and IntelliSense activate automatically The extension activates when it detects files matching `**/.journium/trackers/**/*.yml` or `**/.journium/trackers/**/*.yaml`. How It Works [#how-it-works] The extension configures the [Red Hat YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) to validate tracker files using the Journium schema. When activated, it adds this configuration to your workspace settings: ```json { "yaml.schemas": { "https://journium.app/schemas/journium-insight-tracker.schema.json": [ "**/.journium/trackers/**/*.yml", "**/.journium/trackers/**/*.yaml" ] } } ``` This configuration: * Only affects files under `.journium/trackers/`—other YAML files remain unchanged * Persists across sessions * Can be committed to version control to share with your team Manual Configuration [#manual-configuration] If you need to manually trigger configuration, use the Command Palette: 1. Open Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) 2. Run: **Journium: Enable schema validation for this workspace** This is useful for setting up validation before creating tracker files. Requirements [#requirements] * VS Code 1.105.0 or higher (or compatible editor like Cursor) * Red Hat YAML extension (installed automatically as a dependency) Privacy & Performance [#privacy--performance] **Local validation**: All schema validation happens within your editor—no data is sent to external servers. **Zero overhead**: The extension uses VS Code's built-in file index to detect tracker folders without additional file system scans. Troubleshooting [#troubleshooting] Validation Not Working [#validation-not-working] If validation isn't working: 1. Verify your tracker files are under `.journium/trackers/` 2. Check that files have `.yml` or `.yaml` extensions 3. Run the manual configuration command from the Command Palette 4. Reload the window (`Developer: Reload Window`) Removing Validation [#removing-validation] To remove schema validation from your workspace: 1. Open `.vscode/settings.json` in your workspace 2. Remove the `yaml.schemas` entry for `journium-insight-tracker.schema.json` 3. Save the file Resources [#resources] * [GitHub Repository](https://github.com/journium/journium-vscode-extension) * [Report Issues](https://github.com/journium/journium-vscode-extension/issues) * [Tracker Schema Reference](/docs/angular/concepts/insight_trackers/tracker_specification) # Applications (/docs/js/concepts/application) What is an Application? [#what-is-an-application] Applications in Journium map directly to user applications where tracking is enabled. They have a one-to-one mapping with user apps. A Journium app is not a physical app in the traditional sense but a container to hold all configuration and settings related to tracking events, configuring insight trackers, and viewing app insights. How to Create Apps [#how-to-create-apps]
Create Application [#create-application] Go to your [Journium dashboard](https://dashboard.journium.app). If you have no apps you will land at the app listing page. Click on the **Create application** button, give a name for your application, and click **Create application**. Done [#done] When you create an app in Journium, it creates a default Development instance. This is for quick testing.
App Instances [#app-instances] An app can have two types of instances: **Development** and **Production**. These instances are independent of each other in terms of their configuration. The production instance is what you should track for production purposes. All features are available in both instances. You can create a production instance after you test adequately event generation, trackers, and insights in the Development instance. The instances can be switched in the instance selector in the dashboard. The API keys are different for the two instances. Development Instance [#development-instance] The Development instance is created by default when you create an app in Journium. It has lower usage quotas that are suitable for local testing and development purposes. Production Instance [#production-instance] The Production instance is what you should use for tracking in your production environment. You can create a production instance after you have adequately tested event generation, trackers, and insights in the Development instance. Configuration [#configuration] The configuration of an app is done in the [Journium dashboard](https://dashboard.journium.app). You can configure the app by clicking on the app in the dashboard and then clicking on the **Configure** tab in the sidebar. You can provide the configuration parameters directly on the SDK configuration. If not specified, the configuration that you supply in the dashboard will be used. The configuration in the SDK takes precedence over the configuration in the dashboard. The following settings are available. Event Capture settings [#event-capture-settings] This section allows you to configure the event capture settings for the app. Capture Clicks [#capture-clicks] When enabled, Journium will capture clicks on the app. Enable or disable the toggle switch to capture clicks on the app. Capture Form Submissions [#capture-form-submissions] Enable or disable the toggle switch to capture form submissions on the app. Capture Form Changes [#capture-form-changes] Enable or disable the toggle switch to capture form changes on the app. Capture Page Views [#capture-page-views] Journium can capture page views automatically. Enable or disable the toggle switch to capture page views automatically. Performance Settings [#performance-settings] Configure event batching parameters. Flush At [#flush-at] Configure the number of events to accumulate before flushing to the Journium API. Flush Interval (ms) [#flush-interval-ms] Configure the time interval in milliseconds between automatic flushes to the Journium API. # Events (/docs/js/concepts/events) What is an Event? [#what-is-an-event] An event in Journium is a single piece of telemetry data. Its the primary primitive that drives all the analytics and insights. When you use the Journium SDK, you are essentially sending events to Journium. Some events are auto-captured by the SDK, such as page views, clicks, form submissions, and errors, but you can control what you send to Journium. Event Structure [#event-structure] An event in Journium has the following structure: ```typescript { event: string; properties: Record; } ``` * `event`: The name of the event. * `properties`: A record of key-value pairs that you can use to add additional context to the event. Event Types [#event-types] There are two main types of events in Journium: * Custom Events * Auto-captured Events Custom Events [#custom-events] Custom Events are events that you manually send to Journium. You can send any event you want to Journium, and you can add any properties you want to the event. ```ts journium.track('product_viewed', { product_id: 'prod_123', product_name: 'Running Shoes', price: 89.99, currency: 'USD', category: 'Footwear' }); ``` Auto-captured Events [#auto-captured-events] Auto-captured Events are events that are automatically captured by the SDK. They can be enabled or disabled by configuring the SDK. See [Configuration Options](/docs/js/configuration) for more details. **Configuration Precedence** When you configure at the SDK level, it overrides the configuration in the Journium dashboard. The final derived configuration is the combination of the configuration in the Journium dashboard and the configuration in the SDK with the SDK configuration taking precedence. Viewing Events [#viewing-events] You can view events in the Journium dashboard. You can list them at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events) from your application instance page. Event Details [#event-details] You can view the details of an event by clicking on the event in the events listing. Event Simulator [#event-simulator] In your Development instance, you can test your event tracking by using the Event Simulator. It enables you to impersonate your app temporarily and send events on behalf of your app. This isuseful when you have not yet added custom eventsin your app via the SDK and want to test tracker execution based on events You can access it at [Developers | Event Simulation](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/simulation). # Concepts (/docs/js/concepts) Journium is built around the concept of an **Application**. An application in Journium mirrors your own application and is the starting point for all your telemetry. # Insights (/docs/js/concepts/insights) An Insight is the output of a [Insight Tracker](/docs/js/concepts/insight_trackers) run — a concise, AI-generated summary of your application's event data for a given time window. What is an Insight? [#what-is-an-insight] An Insight is a concise, AI-generated analysis of your application's event data, produced each time an [Insight Tracker](/docs/concepts/insight_trackers) runs. The LLM synthesises the structured query results into a natural-language summary using your configured `promptTemplate` — giving you an actionable, human-readable answer to the question your tracker is asking. Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page, ordered newest-first. What Each Insight Contains [#what-each-insight-contains] | Field | Description | | ------------------- | ---------------------------------------------- | | **Tracker** | The Insight Tracker that produced this insight | | **Generated at** | Timestamp of the job execution | | **Analysis window** | The time range analysed, e.g. "last 7 days" | | **Insight text** | The LLM-generated natural-language summary | How Insights are Generated [#how-insights-are-generated] Insights are produced by running a tracker — either on a schedule (`trigger.mode: automatic`) or on-demand (`trigger.mode: manual`). Each run goes through four steps: 1. **Query compilation** — Journium compiles the `analysis` config into analytical queries for the configured `window` 2. **Data retrieval** — queries run against your application's event data and return structured results 3. **Prompt rendering** — results are mapped to template variables and injected into `llm.promptTemplate` 4. **LLM synthesis** — the LLM generates the insight text, which is persisted and displayed See [Insight Trackers](/docs/concepts/insight_trackers) to learn how to configure the trackers that power your insights. Triggering an Insight [#triggering-an-insight] * **Scheduled** — trackers with `trigger.mode: automatic` run on the configured `schedule` (hourly, daily, weekly, or a cron expression). Each run produces a new insight. * **Manual** — trigger a run at any time from the tracker detail page in the dashboard, or via the API. Insight History [#insight-history] Every run appends a new insight to the history — previous insights are never overwritten. Deactivating or deleting a tracker does not remove past insights; the history is retained for reference. # Analysis Jobs (/docs/js/concepts/jobs) A Job in Journium is an execution instance of an [Insight Tracker](/docs/js/concepts/insight_trackers). Jobs are responsible for collecting data, analyzing events, and generating insights based on the tracker's configuration. Each job execution represents a single run of the tracker's workflow, from data collection to insight generation. What are Analysis Jobs? [#what-are-analysis-jobs] Jobs are the automated processes that execute Insight Trackers. When a tracker runs—either manually triggered or automatically scheduled—it creates a job that carries out the entire analysis workflow. Jobs handle the heavy lifting of: * Collecting relevant event data from your application * Reviewing execution history to understand context * Picking up and filtering relevant events based on the tracker configuration * Executing the tracker's instructions step by step * Generating insights when adequate data is available Think of a Job as a single execution of your Insight Tracker's analysis pipeline. Each job represents one attempt to analyze your data and generate insights. How Jobs Work [#how-jobs-work] Jobs execute the Insight Tracker workflow in a series of steps: **Configuration Loading**: The job picks up the configuration from its associated tracker, including event filters, instructions, and execution parameters **Data Collection**: The job collects relevant events from your application based on the tracker's event selection criteria **Execution History Review**: The job examines previous execution history to understand context and avoid redundant analysis **Event Processing**: Relevant events are filtered and prepared for analysis according to the tracker's configuration **Instruction Execution**: The tracker's instructions are executed step by step, analyzing the collected data **Insight Generation**: If adequate data is available, insights are generated and stored. If insufficient data exists, the job completes as a no-op without generating insights Job Execution Modes [#job-execution-modes] Jobs can be triggered in two ways: Manual Execution [#manual-execution] Jobs can be manually triggered for any tracker from the dashboard. This is useful for: * Testing tracker configurations during development * Running ad-hoc analysis on demand * Troubleshooting tracker behavior * Validating tracker setup before enabling scheduled execution To manually trigger a job, navigate to [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) and click the **`Analyze now`** button for the desired tracker. Automatic Execution [#automatic-execution] When a tracker is configured with **Scheduled** trigger mode, jobs are automatically created and executed according to the defined schedule (e.g., daily, weekly, hourly). This enables continuous monitoring and proactive insight generation without manual intervention. Viewing Jobs [#viewing-jobs] You can view all jobs for your application instance at [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs). Jobs List [#jobs-list] The jobs list provides an overview of all job executions, showing: {/* TODO: Add screenshot of jobs listing page from Journium dashboard */} * **Job Status**: Whether the job is pending, running, completed, or failed * **Tracker**: The Insight Tracker that triggered the job * **Execution Time**: When the job was created and executed * **Duration**: How long the job took to complete * **Result**: Whether insights were generated or if it was a no-op Job Details [#job-details] Clicking on a specific job opens the job details page, which provides comprehensive information about the execution: {/* TODO: Add screenshot of job details page from Journium dashboard */} The job details page shows: * **Execution Steps**: A breakdown of each step in the workflow execution * **Data Collected**: Information about the events and data processed during execution * **Job Output**: Detailed logs and output from each step of the execution * **Generated Insights**: Any insights that were created as a result of this job * **Error Information**: If the job failed, details about what went wrong Monitoring Job Execution [#monitoring-job-execution] Monitoring job output is particularly helpful during the process of developing trackers. The detailed execution logs help you: * **Troubleshoot Issues**: Identify where in the workflow a problem occurred * **Validate Configuration**: Verify that your tracker is collecting and processing the expected data * **Optimize Performance**: Understand which steps take the most time * **Debug Logic**: See exactly how your tracker's instructions are being executed By reviewing job details, you can iteratively refine your tracker configuration to ensure it's working as expected and generating meaningful insights. Job States [#job-states] Jobs progress through several states during execution: * **Pending**: The job has been created and is waiting to start execution * **Running**: The job is currently executing the tracker workflow * **Completed**: The job finished successfully (may or may not have generated insights) * **Failed**: The job encountered an error during execution * **No-op**: The job completed but didn't generate insights due to insufficient data No-op Jobs [#no-op-jobs] A job results in a no-op when there isn't adequate data available to execute the tracker's instructions meaningfully. This is a normal occurrence and doesn't indicate an error. Common reasons for no-op jobs include: * Not enough events matching the tracker's event filters * Insufficient data in the specified time window * Events don't contain the necessary data points for analysis No-op jobs are still valuable as they confirm your tracker is running correctly, even when there isn't enough data to generate insights yet. Best Practices [#best-practices] When working with Jobs: **Monitor During Development**: Regularly check job details when developing new trackers to ensure they're working as expected **Review Execution Logs**: Use job output to understand how your tracker processes data and identify potential improvements **Check Job History**: Review past job executions to understand patterns in data availability and insight generation **Use Manual Execution for Testing**: Trigger jobs manually when testing tracker configurations before enabling scheduled execution **Understand No-ops**: Don't be concerned about no-op jobs—they're normal when data is insufficient and indicate your tracker is running correctly **Job Monitoring**: The job details page provides real-time updates during execution, making it easy to monitor long-running jobs and troubleshoot issues as they occur. # Tools (/docs/js/tools) Journium provides a set of developer focussed tools to develop with Journium faster and easier. # MCP Server (/docs/js/tools/mcp-server) The Journium MCP server enables AI agents to interact with Journium documentation, search for information, and access tools directly from your IDE. Built on the [Model Context Protocol](https://modelcontextprotocol.io), it provides seamless integration with AI-powered development environments. What is MCP? [#what-is-mcp] Model Context Protocol (MCP) is an open standard that allows AI agents to securely connect to external tools and data sources. The Journium MCP server exposes documentation search, page retrieval, and workflow prompts to compatible AI assistants. Server Endpoint [#server-endpoint] ``` https://mcp.journium.app/mcp ``` Available Tools [#available-tools] The MCP server provides the following capabilities: docs_search [#docs_search] Search through Journium documentation using semantic search. Returns relevant pages with excerpts showing matched content. docs_getPage [#docs_getpage] Retrieve the full content of a specific documentation page by its route or file path. Returns MDX content, plain text, and frontmatter metadata. docs_listRoutes [#docs_listroutes] Get a list of all available documentation routes. Optionally filter by prefix to explore specific sections. IDE Setup [#ide-setup] Cursor has built-in MCP support. Add the Journium MCP server to your configuration: **Option 1: Using Settings UI** 1. Open **Cursor Settings** 2. Navigate to **Tools & MCP** → **New MCP Server** 3. Add a new MCP server with these details: * **Name**: `mcp-journium` * **Type**: `http` * **URL**: `https://mcp.journium.app/mcp` **Option 2: Edit Configuration File** **macOS/Linux**: `~/.cursor/mcp.json`\ **Windows**: `%APPDATA%\Cursor\mcp.json` ```json title="mcp.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Cursor after saving the configuration. Add the server to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json title="claude_desktop_config.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Claude Desktop after saving the configuration. Cline supports MCP servers through VS Code settings: 1. Open VS Code Settings (`Cmd+,` / `Ctrl+,`) 2. Search for "Cline MCP" 3. Edit `cline.mcpServers` in `settings.json`: ```json title="settings.json" { "cline.mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Reload VS Code after saving the configuration. For other tools that support the Model Context Protocol, consult their documentation for adding HTTP-based MCP servers. **Server Configuration**: * **Type**: `HTTP` * **URL**: `https://mcp.journium.app/mcp` Most MCP-compatible tools accept configuration in a similar JSON format: ```json { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Refer to your tool's documentation for the specific configuration file location and format. Usage [#usage] Once configured, your AI agent can: * **Search documentation**: Ask questions about Journium features, APIs, or concepts * **Retrieve pages**: Get full documentation content for specific topics * **Explore structure**: Discover available documentation routes and sections The agent will automatically use the MCP server when answering Journium-related questions. Example Queries [#example-queries] With the MCP server configured, try asking your AI assistant: * "How do I set up a tracker in Journium?" * "Show me the Journium Next.js SDK documentation" * "How to integrate Journium in my Shopify store?" * "How to identify a user in Journium?" The agent will search the Journium documentation and provide accurate, up-to-date answers. Benefits [#benefits] **Always up-to-date**: The MCP server provides real-time access to the latest documentation—no stale training data. **Contextual assistance**: AI agents can search, retrieve, and reference official documentation while helping you build. **Seamless workflow**: Get answers without leaving your editor or switching to a browser. Privacy & Security [#privacy--security] **Read-only access**: The MCP server provides read-only access to public documentation. It cannot modify data or access private information. **No authentication required**: The server is publicly accessible and does not require API keys or authentication. **Secure connection**: All requests are made over HTTPS to ensure data integrity and privacy. Troubleshooting [#troubleshooting] Server Not Responding [#server-not-responding] If the MCP server isn't working: 1. Verify the URL is correct: `https://mcp.journium.app/mcp` 2. Check your internet connection 3. Restart your IDE or AI assistant 4. Ensure your MCP configuration file has valid JSON syntax AI Agent Not Using MCP Tools [#ai-agent-not-using-mcp-tools] If your AI agent isn't using the MCP server: 1. Confirm the server is properly configured in your tool's settings 2. Restart the application after adding the configuration 3. Try explicitly asking questions about Journium to trigger MCP usage 4. Check your tool's documentation for MCP-specific requirements Resources [#resources] * [Model Context Protocol Specification](https://modelcontextprotocol.io) * [GitHub Repository](https://github.com/journium/journium-docs/tree/main/apps/docs-mcp) * [Report Issues](https://github.com/journium/journium-docs/issues) # VS Code Extension (/docs/js/tools/vscode-extension) The Journium VS Code extension provides real-time validation, auto-completion, and tooling for insight tracker files. Works with VS Code and VS Code-compatible editors like Cursor. Installation [#installation] Recommended: Install from Your IDE [#recommended-install-from-your-ide] The quickest way to install is directly from your editor's Extensions view: 1. Open your editor (VS Code, Cursor, or other compatible IDE) 2. Go to the Extensions view (`Cmd+Shift+X` / `Ctrl+Shift+X`) 3. Search for "Journium" 4. Click Install Alternative: Direct Download [#alternative-direct-download] You can also install directly from these registries: * **VS Code users**: [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=Journium.journium) * **Cursor and other editors**: [Open VSX Registry](https://open-vsx.org/extension/Journium/journium) Many VS Code-compatible editors like Cursor use the Open VSX Registry as their extension source. Features [#features] Automatic Activation [#automatic-activation] The extension activates automatically when it detects tracker files in `.journium/trackers/` within your workspace. No manual configuration required. Real-time Schema Validation [#real-time-schema-validation] Get instant feedback as you write tracker YAML files. The extension validates all files under `.journium/trackers/` against the Journium insight tracker schema, catching errors before deployment. IntelliSense Support [#intellisense-support] Benefit from auto-completion, hover documentation, and inline schema hints while editing tracker files. Write trackers faster with contextual suggestions. Monorepo Ready [#monorepo-ready] Works seamlessly with monorepos and nested folder structures. The extension detects tracker files at any depth within your workspace. Getting Started [#getting-started] Once installed, the extension works automatically: 1. Create or open a workspace containing a `.journium/trackers/` folder 2. Add YAML files to define your trackers 3. Start editing—validation and IntelliSense activate automatically The extension activates when it detects files matching `**/.journium/trackers/**/*.yml` or `**/.journium/trackers/**/*.yaml`. How It Works [#how-it-works] The extension configures the [Red Hat YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) to validate tracker files using the Journium schema. When activated, it adds this configuration to your workspace settings: ```json { "yaml.schemas": { "https://journium.app/schemas/journium-insight-tracker.schema.json": [ "**/.journium/trackers/**/*.yml", "**/.journium/trackers/**/*.yaml" ] } } ``` This configuration: * Only affects files under `.journium/trackers/`—other YAML files remain unchanged * Persists across sessions * Can be committed to version control to share with your team Manual Configuration [#manual-configuration] If you need to manually trigger configuration, use the Command Palette: 1. Open Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) 2. Run: **Journium: Enable schema validation for this workspace** This is useful for setting up validation before creating tracker files. Requirements [#requirements] * VS Code 1.105.0 or higher (or compatible editor like Cursor) * Red Hat YAML extension (installed automatically as a dependency) Privacy & Performance [#privacy--performance] **Local validation**: All schema validation happens within your editor—no data is sent to external servers. **Zero overhead**: The extension uses VS Code's built-in file index to detect tracker folders without additional file system scans. Troubleshooting [#troubleshooting] Validation Not Working [#validation-not-working] If validation isn't working: 1. Verify your tracker files are under `.journium/trackers/` 2. Check that files have `.yml` or `.yaml` extensions 3. Run the manual configuration command from the Command Palette 4. Reload the window (`Developer: Reload Window`) Removing Validation [#removing-validation] To remove schema validation from your workspace: 1. Open `.vscode/settings.json` in your workspace 2. Remove the `yaml.schemas` entry for `journium-insight-tracker.schema.json` 3. Save the file Resources [#resources] * [GitHub Repository](https://github.com/journium/journium-vscode-extension) * [Report Issues](https://github.com/journium/journium-vscode-extension/issues) * [Tracker Schema Reference](/docs/js/concepts/insight_trackers/tracker_specification) # Applications (/docs/react/concepts/application) What is an Application? [#what-is-an-application] Applications in Journium map directly to user applications where tracking is enabled. They have a one-to-one mapping with user apps. A Journium app is not a physical app in the traditional sense but a container to hold all configuration and settings related to tracking events, configuring insight trackers, and viewing app insights. How to Create Apps [#how-to-create-apps]
Create Application [#create-application] Go to your [Journium dashboard](https://dashboard.journium.app). If you have no apps you will land at the app listing page. Click on the **Create application** button, give a name for your application, and click **Create application**. Done [#done] When you create an app in Journium, it creates a default Development instance. This is for quick testing.
App Instances [#app-instances] An app can have two types of instances: **Development** and **Production**. These instances are independent of each other in terms of their configuration. The production instance is what you should track for production purposes. All features are available in both instances. You can create a production instance after you test adequately event generation, trackers, and insights in the Development instance. The instances can be switched in the instance selector in the dashboard. The API keys are different for the two instances. Development Instance [#development-instance] The Development instance is created by default when you create an app in Journium. It has lower usage quotas that are suitable for local testing and development purposes. Production Instance [#production-instance] The Production instance is what you should use for tracking in your production environment. You can create a production instance after you have adequately tested event generation, trackers, and insights in the Development instance. Configuration [#configuration] The configuration of an app is done in the [Journium dashboard](https://dashboard.journium.app). You can configure the app by clicking on the app in the dashboard and then clicking on the **Configure** tab in the sidebar. You can provide the configuration parameters directly on the SDK configuration. If not specified, the configuration that you supply in the dashboard will be used. The configuration in the SDK takes precedence over the configuration in the dashboard. The following settings are available. Event Capture settings [#event-capture-settings] This section allows you to configure the event capture settings for the app. Capture Clicks [#capture-clicks] When enabled, Journium will capture clicks on the app. Enable or disable the toggle switch to capture clicks on the app. Capture Form Submissions [#capture-form-submissions] Enable or disable the toggle switch to capture form submissions on the app. Capture Form Changes [#capture-form-changes] Enable or disable the toggle switch to capture form changes on the app. Capture Page Views [#capture-page-views] Journium can capture page views automatically. Enable or disable the toggle switch to capture page views automatically. Performance Settings [#performance-settings] Configure event batching parameters. Flush At [#flush-at] Configure the number of events to accumulate before flushing to the Journium API. Flush Interval (ms) [#flush-interval-ms] Configure the time interval in milliseconds between automatic flushes to the Journium API. # Events (/docs/react/concepts/events) What is an Event? [#what-is-an-event] An event in Journium is a single piece of telemetry data. Its the primary primitive that drives all the analytics and insights. When you use the Journium SDK, you are essentially sending events to Journium. Some events are auto-captured by the SDK, such as page views, clicks, form submissions, and errors, but you can control what you send to Journium. Event Structure [#event-structure] An event in Journium has the following structure: ```typescript { event: string; properties: Record; } ``` * `event`: The name of the event. * `properties`: A record of key-value pairs that you can use to add additional context to the event. Event Types [#event-types] There are two main types of events in Journium: * Custom Events * Auto-captured Events Custom Events [#custom-events] Custom Events are events that you manually send to Journium. You can send any event you want to Journium, and you can add any properties you want to the event. ```tsx title="app/your-path/page.tsx" import { useTrackEvent } from '@journium/react'; function ProductPage() { const trackEvent = useTrackEvent(); const handlePurchase = () => { trackEvent('purchase_started', { product_id: 'prod_123', page: 'product_detail', value: 29.99 }); }; return ; } ``` Auto-captured Events [#auto-captured-events] Auto-captured Events are events that are automatically captured by the SDK. They can be enabled or disabled by configuring the SDK. See [React Configuration](/docs/react/configuration) or [Configuration](/docs/js/configuration) for more details. **Configuration Precedence** When you configure at the SDK level, it overrides the configuration in the Journium dashboard. The final derived configuration is the combination of the configuration in the Journium dashboard and the configuration in the SDK with the SDK configuration taking precedence. Viewing Events [#viewing-events] You can view events in the Journium dashboard. You can list them at [Developers | Events](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/events) from your application instance page. Event Details [#event-details] You can view the details of an event by clicking on the event in the events listing. Event Simulator [#event-simulator] In your Development instance, you can test your event tracking by using the Event Simulator. It enables you to impersonate your app temporarily and send events on behalf of your app. This isuseful when you have not yet added custom eventsin your app via the SDK and want to test tracker execution based on events You can access it at [Developers | Event Simulation](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/simulation). # Concepts (/docs/react/concepts) Journium is built around the concept of an **Application**. An application in Journium mirrors your own application and is the starting point for all your telemetry. # Insights (/docs/react/concepts/insights) An Insight is the output of a [Insight Tracker](/docs/react/concepts/insight_trackers) run — a concise, AI-generated summary of your application's event data for a given time window. What is an Insight? [#what-is-an-insight] An Insight is a concise, AI-generated analysis of your application's event data, produced each time an [Insight Tracker](/docs/concepts/insight_trackers) runs. The LLM synthesises the structured query results into a natural-language summary using your configured `promptTemplate` — giving you an actionable, human-readable answer to the question your tracker is asking. Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page, ordered newest-first. What Each Insight Contains [#what-each-insight-contains] | Field | Description | | ------------------- | ---------------------------------------------- | | **Tracker** | The Insight Tracker that produced this insight | | **Generated at** | Timestamp of the job execution | | **Analysis window** | The time range analysed, e.g. "last 7 days" | | **Insight text** | The LLM-generated natural-language summary | How Insights are Generated [#how-insights-are-generated] Insights are produced by running a tracker — either on a schedule (`trigger.mode: automatic`) or on-demand (`trigger.mode: manual`). Each run goes through four steps: 1. **Query compilation** — Journium compiles the `analysis` config into analytical queries for the configured `window` 2. **Data retrieval** — queries run against your application's event data and return structured results 3. **Prompt rendering** — results are mapped to template variables and injected into `llm.promptTemplate` 4. **LLM synthesis** — the LLM generates the insight text, which is persisted and displayed See [Insight Trackers](/docs/concepts/insight_trackers) to learn how to configure the trackers that power your insights. Triggering an Insight [#triggering-an-insight] * **Scheduled** — trackers with `trigger.mode: automatic` run on the configured `schedule` (hourly, daily, weekly, or a cron expression). Each run produces a new insight. * **Manual** — trigger a run at any time from the tracker detail page in the dashboard, or via the API. Insight History [#insight-history] Every run appends a new insight to the history — previous insights are never overwritten. Deactivating or deleting a tracker does not remove past insights; the history is retained for reference. # Analysis Jobs (/docs/react/concepts/jobs) A Job in Journium is an execution instance of an [Insight Tracker](/docs/react/concepts/insight_trackers). Jobs are responsible for collecting data, analyzing events, and generating insights based on the tracker's configuration. Each job execution represents a single run of the tracker's workflow, from data collection to insight generation. What are Analysis Jobs? [#what-are-analysis-jobs] Jobs are the automated processes that execute Insight Trackers. When a tracker runs—either manually triggered or automatically scheduled—it creates a job that carries out the entire analysis workflow. Jobs handle the heavy lifting of: * Collecting relevant event data from your application * Reviewing execution history to understand context * Picking up and filtering relevant events based on the tracker configuration * Executing the tracker's instructions step by step * Generating insights when adequate data is available Think of a Job as a single execution of your Insight Tracker's analysis pipeline. Each job represents one attempt to analyze your data and generate insights. How Jobs Work [#how-jobs-work] Jobs execute the Insight Tracker workflow in a series of steps: **Configuration Loading**: The job picks up the configuration from its associated tracker, including event filters, instructions, and execution parameters **Data Collection**: The job collects relevant events from your application based on the tracker's event selection criteria **Execution History Review**: The job examines previous execution history to understand context and avoid redundant analysis **Event Processing**: Relevant events are filtered and prepared for analysis according to the tracker's configuration **Instruction Execution**: The tracker's instructions are executed step by step, analyzing the collected data **Insight Generation**: If adequate data is available, insights are generated and stored. If insufficient data exists, the job completes as a no-op without generating insights Job Execution Modes [#job-execution-modes] Jobs can be triggered in two ways: Manual Execution [#manual-execution] Jobs can be manually triggered for any tracker from the dashboard. This is useful for: * Testing tracker configurations during development * Running ad-hoc analysis on demand * Troubleshooting tracker behavior * Validating tracker setup before enabling scheduled execution To manually trigger a job, navigate to [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) and click the **`Analyze now`** button for the desired tracker. Automatic Execution [#automatic-execution] When a tracker is configured with **Scheduled** trigger mode, jobs are automatically created and executed according to the defined schedule (e.g., daily, weekly, hourly). This enables continuous monitoring and proactive insight generation without manual intervention. Viewing Jobs [#viewing-jobs] You can view all jobs for your application instance at [Developers | Jobs](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/jobs). Jobs List [#jobs-list] The jobs list provides an overview of all job executions, showing: {/* TODO: Add screenshot of jobs listing page from Journium dashboard */} * **Job Status**: Whether the job is pending, running, completed, or failed * **Tracker**: The Insight Tracker that triggered the job * **Execution Time**: When the job was created and executed * **Duration**: How long the job took to complete * **Result**: Whether insights were generated or if it was a no-op Job Details [#job-details] Clicking on a specific job opens the job details page, which provides comprehensive information about the execution: {/* TODO: Add screenshot of job details page from Journium dashboard */} The job details page shows: * **Execution Steps**: A breakdown of each step in the workflow execution * **Data Collected**: Information about the events and data processed during execution * **Job Output**: Detailed logs and output from each step of the execution * **Generated Insights**: Any insights that were created as a result of this job * **Error Information**: If the job failed, details about what went wrong Monitoring Job Execution [#monitoring-job-execution] Monitoring job output is particularly helpful during the process of developing trackers. The detailed execution logs help you: * **Troubleshoot Issues**: Identify where in the workflow a problem occurred * **Validate Configuration**: Verify that your tracker is collecting and processing the expected data * **Optimize Performance**: Understand which steps take the most time * **Debug Logic**: See exactly how your tracker's instructions are being executed By reviewing job details, you can iteratively refine your tracker configuration to ensure it's working as expected and generating meaningful insights. Job States [#job-states] Jobs progress through several states during execution: * **Pending**: The job has been created and is waiting to start execution * **Running**: The job is currently executing the tracker workflow * **Completed**: The job finished successfully (may or may not have generated insights) * **Failed**: The job encountered an error during execution * **No-op**: The job completed but didn't generate insights due to insufficient data No-op Jobs [#no-op-jobs] A job results in a no-op when there isn't adequate data available to execute the tracker's instructions meaningfully. This is a normal occurrence and doesn't indicate an error. Common reasons for no-op jobs include: * Not enough events matching the tracker's event filters * Insufficient data in the specified time window * Events don't contain the necessary data points for analysis No-op jobs are still valuable as they confirm your tracker is running correctly, even when there isn't enough data to generate insights yet. Best Practices [#best-practices] When working with Jobs: **Monitor During Development**: Regularly check job details when developing new trackers to ensure they're working as expected **Review Execution Logs**: Use job output to understand how your tracker processes data and identify potential improvements **Check Job History**: Review past job executions to understand patterns in data availability and insight generation **Use Manual Execution for Testing**: Trigger jobs manually when testing tracker configurations before enabling scheduled execution **Understand No-ops**: Don't be concerned about no-op jobs—they're normal when data is insufficient and indicate your tracker is running correctly **Job Monitoring**: The job details page provides real-time updates during execution, making it easy to monitor long-running jobs and troubleshoot issues as they occur. # Hooks Reference (/docs/react/hooks) Journium offers a comprehensive suite of hooks that expose low-level access to analytics, event tracking, and user identification. With Journium hooks, you can access and manage user data, handle event tracking, and generate a variety of insights from your data. Hooks [#hooks] * [`useIdentify()`](/docs/hooks/use-identify) * [`useTrackEvent()`](/docs/hooks/use-track-event) * [`useReset()`](/docs/hooks/use-reset) # useIdentify() (/docs/react/hooks/use-identify) Identify a User [#identify-a-user] The `useIdentify()` hook is used to identify a user when they log in or sign up. ```tsx title="pages/login.tsx" import React from 'react'; // [!code ++:1] import { useIdentify } from '@journium/react'; function LoginForm() { // [!code ++:1] const identify = useIdentify(); const handleLogin = async (email, password) => { const user = await loginUser(email, password); // [!code ++:4] identify(user.id, { name: user.name, email: user.email }); }; return (
{/* Login form fields */}
); } ``` # useReset() (/docs/react/hooks/use-reset) Reset user identity [#reset-user-identity] The `useReset()` hook is used to reset user identity when they log out or when you want to clear the user's identity. ```tsx title="pages/logout.tsx" import React from 'react'; // [!code ++:1] import { useReset } from '@journium/react'; function LogoutButton() { // [!code ++:1] const reset = useReset(); const handleLogout = async () => { await logoutUser(); // [!code ++:1] reset(); }; return ; } ``` # useTrackEvent() (/docs/react/hooks/use-track-event) Track a custom event [#track-a-custom-event] The `useTrackEvent()` hook is used to track a custom event. You can track any event that you want to track in your application. ```tsx title="pages/dashboard.tsx" import React from 'react'; // [!code ++:1] import { useTrackEvent } from '@journium/react'; function SignupButton() { // [!code ++:1] const trackEvent = useTrackEvent(); const handleSignup = () => { // [!code ++:5] trackEvent('user_signup', { method: 'email', source: 'landing_page', plan: 'free' }); }; return ; } ``` # Tools (/docs/react/tools) Journium provides a set of developer focussed tools to develop with Journium faster and easier. # MCP Server (/docs/react/tools/mcp-server) The Journium MCP server enables AI agents to interact with Journium documentation, search for information, and access tools directly from your IDE. Built on the [Model Context Protocol](https://modelcontextprotocol.io), it provides seamless integration with AI-powered development environments. What is MCP? [#what-is-mcp] Model Context Protocol (MCP) is an open standard that allows AI agents to securely connect to external tools and data sources. The Journium MCP server exposes documentation search, page retrieval, and workflow prompts to compatible AI assistants. Server Endpoint [#server-endpoint] ``` https://mcp.journium.app/mcp ``` Available Tools [#available-tools] The MCP server provides the following capabilities: docs_search [#docs_search] Search through Journium documentation using semantic search. Returns relevant pages with excerpts showing matched content. docs_getPage [#docs_getpage] Retrieve the full content of a specific documentation page by its route or file path. Returns MDX content, plain text, and frontmatter metadata. docs_listRoutes [#docs_listroutes] Get a list of all available documentation routes. Optionally filter by prefix to explore specific sections. IDE Setup [#ide-setup] Cursor has built-in MCP support. Add the Journium MCP server to your configuration: **Option 1: Using Settings UI** 1. Open **Cursor Settings** 2. Navigate to **Tools & MCP** → **New MCP Server** 3. Add a new MCP server with these details: * **Name**: `mcp-journium` * **Type**: `http` * **URL**: `https://mcp.journium.app/mcp` **Option 2: Edit Configuration File** **macOS/Linux**: `~/.cursor/mcp.json`\ **Windows**: `%APPDATA%\Cursor\mcp.json` ```json title="mcp.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Cursor after saving the configuration. Add the server to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json title="claude_desktop_config.json" { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Restart Claude Desktop after saving the configuration. Cline supports MCP servers through VS Code settings: 1. Open VS Code Settings (`Cmd+,` / `Ctrl+,`) 2. Search for "Cline MCP" 3. Edit `cline.mcpServers` in `settings.json`: ```json title="settings.json" { "cline.mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Reload VS Code after saving the configuration. For other tools that support the Model Context Protocol, consult their documentation for adding HTTP-based MCP servers. **Server Configuration**: * **Type**: `HTTP` * **URL**: `https://mcp.journium.app/mcp` Most MCP-compatible tools accept configuration in a similar JSON format: ```json { "mcpServers": { "mcp-journium": { "type": "http", "url": "https://mcp.journium.app/mcp" } } } ``` Refer to your tool's documentation for the specific configuration file location and format. Usage [#usage] Once configured, your AI agent can: * **Search documentation**: Ask questions about Journium features, APIs, or concepts * **Retrieve pages**: Get full documentation content for specific topics * **Explore structure**: Discover available documentation routes and sections The agent will automatically use the MCP server when answering Journium-related questions. Example Queries [#example-queries] With the MCP server configured, try asking your AI assistant: * "How do I set up a tracker in Journium?" * "Show me the Journium Next.js SDK documentation" * "How to integrate Journium in my Shopify store?" * "How to identify a user in Journium?" The agent will search the Journium documentation and provide accurate, up-to-date answers. Benefits [#benefits] **Always up-to-date**: The MCP server provides real-time access to the latest documentation—no stale training data. **Contextual assistance**: AI agents can search, retrieve, and reference official documentation while helping you build. **Seamless workflow**: Get answers without leaving your editor or switching to a browser. Privacy & Security [#privacy--security] **Read-only access**: The MCP server provides read-only access to public documentation. It cannot modify data or access private information. **No authentication required**: The server is publicly accessible and does not require API keys or authentication. **Secure connection**: All requests are made over HTTPS to ensure data integrity and privacy. Troubleshooting [#troubleshooting] Server Not Responding [#server-not-responding] If the MCP server isn't working: 1. Verify the URL is correct: `https://mcp.journium.app/mcp` 2. Check your internet connection 3. Restart your IDE or AI assistant 4. Ensure your MCP configuration file has valid JSON syntax AI Agent Not Using MCP Tools [#ai-agent-not-using-mcp-tools] If your AI agent isn't using the MCP server: 1. Confirm the server is properly configured in your tool's settings 2. Restart the application after adding the configuration 3. Try explicitly asking questions about Journium to trigger MCP usage 4. Check your tool's documentation for MCP-specific requirements Resources [#resources] * [Model Context Protocol Specification](https://modelcontextprotocol.io) * [GitHub Repository](https://github.com/journium/journium-docs/tree/main/apps/docs-mcp) * [Report Issues](https://github.com/journium/journium-docs/issues) # VS Code Extension (/docs/react/tools/vscode-extension) The Journium VS Code extension provides real-time validation, auto-completion, and tooling for insight tracker files. Works with VS Code and VS Code-compatible editors like Cursor. Installation [#installation] Recommended: Install from Your IDE [#recommended-install-from-your-ide] The quickest way to install is directly from your editor's Extensions view: 1. Open your editor (VS Code, Cursor, or other compatible IDE) 2. Go to the Extensions view (`Cmd+Shift+X` / `Ctrl+Shift+X`) 3. Search for "Journium" 4. Click Install Alternative: Direct Download [#alternative-direct-download] You can also install directly from these registries: * **VS Code users**: [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=Journium.journium) * **Cursor and other editors**: [Open VSX Registry](https://open-vsx.org/extension/Journium/journium) Many VS Code-compatible editors like Cursor use the Open VSX Registry as their extension source. Features [#features] Automatic Activation [#automatic-activation] The extension activates automatically when it detects tracker files in `.journium/trackers/` within your workspace. No manual configuration required. Real-time Schema Validation [#real-time-schema-validation] Get instant feedback as you write tracker YAML files. The extension validates all files under `.journium/trackers/` against the Journium insight tracker schema, catching errors before deployment. IntelliSense Support [#intellisense-support] Benefit from auto-completion, hover documentation, and inline schema hints while editing tracker files. Write trackers faster with contextual suggestions. Monorepo Ready [#monorepo-ready] Works seamlessly with monorepos and nested folder structures. The extension detects tracker files at any depth within your workspace. Getting Started [#getting-started] Once installed, the extension works automatically: 1. Create or open a workspace containing a `.journium/trackers/` folder 2. Add YAML files to define your trackers 3. Start editing—validation and IntelliSense activate automatically The extension activates when it detects files matching `**/.journium/trackers/**/*.yml` or `**/.journium/trackers/**/*.yaml`. How It Works [#how-it-works] The extension configures the [Red Hat YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) to validate tracker files using the Journium schema. When activated, it adds this configuration to your workspace settings: ```json { "yaml.schemas": { "https://journium.app/schemas/journium-insight-tracker.schema.json": [ "**/.journium/trackers/**/*.yml", "**/.journium/trackers/**/*.yaml" ] } } ``` This configuration: * Only affects files under `.journium/trackers/`—other YAML files remain unchanged * Persists across sessions * Can be committed to version control to share with your team Manual Configuration [#manual-configuration] If you need to manually trigger configuration, use the Command Palette: 1. Open Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) 2. Run: **Journium: Enable schema validation for this workspace** This is useful for setting up validation before creating tracker files. Requirements [#requirements] * VS Code 1.105.0 or higher (or compatible editor like Cursor) * Red Hat YAML extension (installed automatically as a dependency) Privacy & Performance [#privacy--performance] **Local validation**: All schema validation happens within your editor—no data is sent to external servers. **Zero overhead**: The extension uses VS Code's built-in file index to detect tracker folders without additional file system scans. Troubleshooting [#troubleshooting] Validation Not Working [#validation-not-working] If validation isn't working: 1. Verify your tracker files are under `.journium/trackers/` 2. Check that files have `.yml` or `.yaml` extensions 3. Run the manual configuration command from the Command Palette 4. Reload the window (`Developer: Reload Window`) Removing Validation [#removing-validation] To remove schema validation from your workspace: 1. Open `.vscode/settings.json` in your workspace 2. Remove the `yaml.schemas` entry for `journium-insight-tracker.schema.json` 3. Save the file Resources [#resources] * [GitHub Repository](https://github.com/journium/journium-vscode-extension) * [Report Issues](https://github.com/journium/journium-vscode-extension/issues) * [Tracker Schema Reference](/docs/react/concepts/insight_trackers/tracker_specification) # Creating Insight Trackers (/docs/concepts/insight_trackers/creating_trackers) Trackers can be created in three ways. The **NL Builder** lets you describe what you want to track in plain English and generates a fully-configured tracker for you. The **YAML Editor** gives you direct control over the tracker specification. **Git Repository** sync lets you version control your tracker files and deploy them automatically on push. Irrespective of the method you use, the result is always a YAML tracker specification file that you can inspect and edit at any time. Trackers are specific to an application instance. Trackers configured for one application instance are not shared with other instances. Describe in English (NL Builder) [#describe-in-english-nl-builder] The NL Builder is the fastest way to create a new tracker. Describe what you want to measure in plain English — Journium's AI assistant will choose the right analysis type, configure the fields, and generate a complete tracker spec for you. You can access the NL Builder from [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) by selecting the **Describe in English** option. The NL Builder walks you through four steps: 1. Describe Your Goal [#1-describe-your-goal] Type a natural-language description of the insight you want. Be as specific as you like — include event names, time windows, and any segmentation properties you care about. Examples: * *"Track how many users drop off during checkout — from cart viewed through order completed, broken down by plan."* * *"Show me 30-day retention after signup, with weekly cohort groups."* * *"Alert me when error event rates spike more than 2 standard deviations above the 14-day rolling average."* 2. Clarify (if needed) [#2-clarify-if-needed] If your description is ambiguous, Journium may ask a small number of clarifying questions (e.g. which events to treat as the start and end of an activation window). Answer them in the same text field — the builder will update its draft accordingly. 3. Review the Draft [#3-review-the-draft] Once the pipeline completes, you'll see a full YAML tracker spec in the editor along with **instrumentation notes** — a checklist of any new events or properties your tracker requires that haven't been seen in your app yet. Review the spec, make any manual adjustments in the YAML editor, and decide on a status: * **Save as Draft** — saves the tracker in draft status (no scheduled runs) * **Save & Activate** — saves and activates the tracker immediately 4. Instrument Your Events (if required) [#4-instrument-your-events-if-required] If the instrumentation notes list events or properties your app doesn't currently send, follow the instrumentation guide for your SDK to start capturing them before activating the tracker. **Test Data**: The NL Builder also generates a sample test-events file (downloadable from the tracker detail page) so you can verify the tracker's analysis logic before real events arrive. Using YAML Editor [#using-yaml-editor] You can create a new tracker manually using the tracker specification YAML. This gives you full control over every configuration field. Go to [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) and choose the **Use YAML Editor** option. The editor is pre-filled with a sample tracker specification. Edit the YAML to match your requirements. The editor provides a validation status badge to indicate the validity of the YAML. If errors exist, they are shown in the gutter. Hover over the error to see the message. You can save only when the YAML is valid. Example YAML [#example-yaml] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Data: {{dataAsJson}} Give 2-3 concrete optimization recommendations. maxOutputTokens: 500 ``` See the [Tracker Specification](/docs/concepts/insight_trackers/tracker_specification) reference for the complete list of fields. Best Practices [#best-practices] When authoring tracker YAML directly: 1. **Choose the right analysis type**: Match the `analysis.type` to the question you're asking — see [Analysis Types](/docs/concepts/insight_trackers/analysis_types) for guidance 2. **Use only valid template variables**: Each analysis type exposes a specific set of `{{variables}}` — using an unsupported variable will be rejected at save time 3. **Set appropriate schedules**: Use `automatic` with a `schedule` for continuous monitoring; use `manual` for exploratory or ad-hoc analysis 4. **Keep prompts focused**: One clear question per tracker produces better insights than an open-ended catch-all prompt 5. **Use `privacy` to protect PII**: List any user-identifying properties in `excludeProperties` or `hashProperties` **Default Tracker**: When you create an app in Journium, a default "User Engagement" tracker is automatically created. This tracker helps you test data ingestion and insight generation with your initial events. From Git Repository [#from-git-repository] You can connect a repository to your application instance at [Developers | Insight Trackers | Link Git Repository](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new/git). Tracker files from your git repository will be synced to your application instance. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. **Note**: Your tracker YAML files should be in the .journium/trackers directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker YAML files should be at `https://github.com/my-org/my-repo/tree/main/.journium/trackers`. # Insight Trackers (/docs/concepts/insight_trackers) An Insight Tracker in Journium is a declarative configuration that tells Journium what to analyze and how often. It acts as a bridge between your raw [Events](/docs/concepts/events) and the [Insights](/docs/concepts/insights) that help you understand your application's behavior. What are Insight Trackers? [#what-are-insight-trackers] Insight Trackers are the core of Journium's **Insights as Code** approach. Instead of manually querying data or building dashboards, you define what you want to know about your application, and Journium's AI-driven analytics engine automatically analyzes your event data to generate concise, actionable insights. Think of an Insight Tracker as a continuous data analyst that: * Runs a **structured analysis** against your events (funnel, retention, churn, trend, and more) * Synthesizes findings into a natural-language insight using an LLM with your custom prompt * Runs automatically on a schedule or on-demand * Surfaces results on your application's Insights page Each tracker's `analysis` block selects one of nine structured analysis types — covering funnel drop-off, cohort retention, activation rates, churn risk, feature adoption, anomaly detection, conversion rates, cohort comparisons, and trend/growth analysis. This structured approach replaces freeform raw-event queries and produces higher-quality, more consistent insights. How Insight Trackers Work [#how-insight-trackers-work] Insight Trackers transform raw telemetry data into human-readable insights through an AI-driven pipeline: 1. **Query Compilation**: Journium compiles your `analysis` config into optimised analytical queries for the chosen `window` period 2. **Data Retrieval**: The compiled queries run against your event data and return structured results (conversion rates, cohort tables, anomaly scores, etc.) 3. **Payload Building**: The structured results are mapped to named template variables and injected into your `llm.promptTemplate` 4. **Insight Generation**: The LLM synthesises the data into a concise, natural-language insight backed by verifiable numbers 5. **Delivery**: Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page This process eliminates the need for manual data exploration, SQL queries, or dashboard interpretation. You can list an application instance's insight trackers at [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) from your application instance page. Choosing an Analysis Type [#choosing-an-analysis-type] The `analysis.type` field determines what Journium computes and which template variables are available in your prompt. Choose the type that best matches the question you want to answer: | If you want to… | Use type | | ------------------------------------------------------------ | ----------------- | | See where users drop off across ordered steps | `funnel` | | Track cohort return rates over time (D1 / D7 / D30) | `retention` | | Measure what % of new users reach the first value moment | `activation` | | Identify users who have gone silent and are at churn risk | `churn` | | Know what fraction of active users have tried a feature | `featureAdoption` | | Detect unusual spikes or dips vs. a statistical baseline | `anomaly` | | Compute a simple A → B conversion rate | `conversion` | | Compare a metric across cohorts defined by join date or tier | `cohort` | | Plot event counts or unique users per time period | `trend` | See [Analysis Types](/docs/concepts/insight_trackers/analysis_types) for the full reference for each type. # Tracker Repositories (/docs/concepts/insight_trackers/tracker_repositories) Tracker location [#tracker-location] As a best practice, it is recommended to use a Git repository to store your trackers. You can connect a repository to your application instance to deploy and manage your trackers. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. Your tracker yaml files should be in the `.journium/trackers` directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker yaml files should be in the `https://github.com/my-org/my-repo/.journium/trackers` directory. Recommended Layout [#recommended-layout] You can colocate your trackers in your source code repository (recommended) or in a seperate repository as well. Here's how your repository should look like for the best practice: Linking a Git Repository [#linking-a-git-repository] Follw the steps below to to link a git repository containing tracker yaml files to your application instance.
Connect Git Account [#connect-git-account] To link a repository, you need to have a Git integration configured in Journium. You can configure a Git integration at [Integrations | Git](https://dashboard.journium.app/integrations/git) by connecting your GitHub account. For other Git providers, drop us a note at [support@journium.app](mailto:support@journium.app). The GitHub App for Journium is used to connect your GitHub repositories to your application instance. You can provide permissions to the specific repositories you want to connect to your application instance. Link Repository [#link-repository] After you have configured a Git integration, you can link a repository to your application instance. View Deployment History [#view-deployment-history] Navigate to the Tracker Repositories page to view the deployment history of your trackers. When you push changes to the deployment branch, the trackers will be synced to your application instance. This is called a deployment. Files are deployed to the application instance only if the YAML is valid.
# Tracker Specification (/docs/concepts/insight_trackers/tracker_specification) A Journium InsightTracker is defined using a structured YAML format that follows the [InsightTracker schema](https://journium.app/schemas/journium-insight-tracker.schema.json). Top-Level Properties [#top-level-properties] metadata Properties [#metadata-properties] spec Properties [#spec-properties] trigger Properties [#trigger-properties] " }`', required: false, }, }} /> window Properties [#window-properties] ", end: "" }`', required: true, }, granularity: { description: 'Optional time-bucket size for time-series analysis types (trend, anomaly). Ignored by non-time-series types.', type: 'string', typeDescription: '`"hour"` | `"day"` | `"week"` | `"month"`', required: false, }, timezone: { description: 'Optional IANA timezone used when bucketing time-series data. Defaults to UTC.', type: 'string', typeDescription: 'e.g. `"America/New_York"`, `"Europe/London"`', required: false, }, }} /> *** Shared Primitives [#shared-primitives] These types are referenced by multiple analysis configurations. PropertyFilter [#propertyfilter] Used to narrow the set of events considered by an analysis step. BreakdownDef [#breakdowndef] Segments analysis results by a property dimension. *** Analysis Types [#analysis-types] The `analysis.type` field selects the analysis algorithm. Each type computes different metrics and injects different template variables into your `llm.promptTemplate`. | Type | Description | | ------------------------------------------------------ | ---------------------------------------------------------- | | [`funnel`](./analysis_types/funnel) | Ordered step completion — find where users drop off | | [`retention`](./analysis_types/retention) | Cohort return-rate curves (D1 / D7 / D30) | | [`activation`](./analysis_types/activation) | % of new users who reach the first value moment | | [`churn`](./analysis_types/churn) | Users who were active but have gone silent | | [`featureAdoption`](./analysis_types/feature_adoption) | Fraction of active users who have tried a feature | | [`anomaly`](./analysis_types/anomaly) | Automated spike / dip detection vs. a statistical baseline | | [`conversion`](./analysis_types/conversion) | Simple numerator / denominator conversion rate | | [`cohort`](./analysis_types/cohort) | Compare a metric across cohorts by join date or property | | [`trend`](./analysis_types/trend) | Count events or unique users per time period | | [`custom`](./analysis_types/custom) | Raw event list analysis — not available in the NL Builder | See the [Analysis Types overview](./analysis_types) for per-type configuration reference and examples. *** llm Properties [#llm-properties] Universal Template Variables [#universal-template-variables] These variables are always available in `promptTemplate`, regardless of analysis type: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result from the analysis query, serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Type-specific variables are documented on each analysis type's reference page. *** privacy Properties [#privacy-properties] *** Full Example [#full-example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day timezone: America/New_York analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel with an overall conversion of {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst performing step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 concrete, actionable recommendations to improve conversion. maxOutputTokens: 500 guardrails: citeSources: true privacy: excludeProperties: - email - phone hashProperties: - userId ``` # Creating Insight Trackers (/docs/angular/concepts/insight_trackers/creating_trackers) Trackers can be created in three ways. The **NL Builder** lets you describe what you want to track in plain English and generates a fully-configured tracker for you. The **YAML Editor** gives you direct control over the tracker specification. **Git Repository** sync lets you version control your tracker files and deploy them automatically on push. Irrespective of the method you use, the result is always a YAML tracker specification file that you can inspect and edit at any time. Trackers are specific to an application instance. Trackers configured for one application instance are not shared with other instances. Describe in English (NL Builder) [#describe-in-english-nl-builder] The NL Builder is the fastest way to create a new tracker. Describe what you want to measure in plain English — Journium's AI assistant will choose the right analysis type, configure the fields, and generate a complete tracker spec for you. You can access the NL Builder from [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) by selecting the **Describe in English** option. The NL Builder walks you through four steps: 1. Describe Your Goal [#1-describe-your-goal] Type a natural-language description of the insight you want. Be as specific as you like — include event names, time windows, and any segmentation properties you care about. Examples: * *"Track how many users drop off during checkout — from cart viewed through order completed, broken down by plan."* * *"Show me 30-day retention after signup, with weekly cohort groups."* * *"Alert me when error event rates spike more than 2 standard deviations above the 14-day rolling average."* 2. Clarify (if needed) [#2-clarify-if-needed] If your description is ambiguous, Journium may ask a small number of clarifying questions (e.g. which events to treat as the start and end of an activation window). Answer them in the same text field — the builder will update its draft accordingly. 3. Review the Draft [#3-review-the-draft] Once the pipeline completes, you'll see a full YAML tracker spec in the editor along with **instrumentation notes** — a checklist of any new events or properties your tracker requires that haven't been seen in your app yet. Review the spec, make any manual adjustments in the YAML editor, and decide on a status: * **Save as Draft** — saves the tracker in draft status (no scheduled runs) * **Save & Activate** — saves and activates the tracker immediately 4. Instrument Your Events (if required) [#4-instrument-your-events-if-required] If the instrumentation notes list events or properties your app doesn't currently send, follow the instrumentation guide for your SDK to start capturing them before activating the tracker. **Test Data**: The NL Builder also generates a sample test-events file (downloadable from the tracker detail page) so you can verify the tracker's analysis logic before real events arrive. Using YAML Editor [#using-yaml-editor] You can create a new tracker manually using the tracker specification YAML. This gives you full control over every configuration field. Go to [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) and choose the **Use YAML Editor** option. The editor is pre-filled with a sample tracker specification. Edit the YAML to match your requirements. The editor provides a validation status badge to indicate the validity of the YAML. If errors exist, they are shown in the gutter. Hover over the error to see the message. You can save only when the YAML is valid. Example YAML [#example-yaml] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Data: {{dataAsJson}} Give 2-3 concrete optimization recommendations. maxOutputTokens: 500 ``` See the [Tracker Specification](/docs/concepts/insight_trackers/tracker_specification) reference for the complete list of fields. Best Practices [#best-practices] When authoring tracker YAML directly: 1. **Choose the right analysis type**: Match the `analysis.type` to the question you're asking — see [Analysis Types](/docs/concepts/insight_trackers/analysis_types) for guidance 2. **Use only valid template variables**: Each analysis type exposes a specific set of `{{variables}}` — using an unsupported variable will be rejected at save time 3. **Set appropriate schedules**: Use `automatic` with a `schedule` for continuous monitoring; use `manual` for exploratory or ad-hoc analysis 4. **Keep prompts focused**: One clear question per tracker produces better insights than an open-ended catch-all prompt 5. **Use `privacy` to protect PII**: List any user-identifying properties in `excludeProperties` or `hashProperties` **Default Tracker**: When you create an app in Journium, a default "User Engagement" tracker is automatically created. This tracker helps you test data ingestion and insight generation with your initial events. From Git Repository [#from-git-repository] You can connect a repository to your application instance at [Developers | Insight Trackers | Link Git Repository](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new/git). Tracker files from your git repository will be synced to your application instance. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. **Note**: Your tracker YAML files should be in the .journium/trackers directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker YAML files should be at `https://github.com/my-org/my-repo/tree/main/.journium/trackers`. # Insight Trackers (/docs/angular/concepts/insight_trackers) An Insight Tracker in Journium is a declarative configuration that tells Journium what to analyze and how often. It acts as a bridge between your raw [Events](/docs/angular/concepts/events) and the [Insights](/docs/angular/concepts/insights) that help you understand your application's behavior. What are Insight Trackers? [#what-are-insight-trackers] Insight Trackers are the core of Journium's **Insights as Code** approach. Instead of manually querying data or building dashboards, you define what you want to know about your application, and Journium's AI-driven analytics engine automatically analyzes your event data to generate concise, actionable insights. Think of an Insight Tracker as a continuous data analyst that: * Runs a **structured analysis** against your events (funnel, retention, churn, trend, and more) * Synthesizes findings into a natural-language insight using an LLM with your custom prompt * Runs automatically on a schedule or on-demand * Surfaces results on your application's Insights page Each tracker's `analysis` block selects one of nine structured analysis types — covering funnel drop-off, cohort retention, activation rates, churn risk, feature adoption, anomaly detection, conversion rates, cohort comparisons, and trend/growth analysis. This structured approach replaces freeform raw-event queries and produces higher-quality, more consistent insights. How Insight Trackers Work [#how-insight-trackers-work] Insight Trackers transform raw telemetry data into human-readable insights through an AI-driven pipeline: 1. **Query Compilation**: Journium compiles your `analysis` config into optimised analytical queries for the chosen `window` period 2. **Data Retrieval**: The compiled queries run against your event data and return structured results (conversion rates, cohort tables, anomaly scores, etc.) 3. **Payload Building**: The structured results are mapped to named template variables and injected into your `llm.promptTemplate` 4. **Insight Generation**: The LLM synthesises the data into a concise, natural-language insight backed by verifiable numbers 5. **Delivery**: Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page This process eliminates the need for manual data exploration, SQL queries, or dashboard interpretation. You can list an application instance's insight trackers at [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) from your application instance page. Choosing an Analysis Type [#choosing-an-analysis-type] The `analysis.type` field determines what Journium computes and which template variables are available in your prompt. Choose the type that best matches the question you want to answer: | If you want to… | Use type | | ------------------------------------------------------------ | ----------------- | | See where users drop off across ordered steps | `funnel` | | Track cohort return rates over time (D1 / D7 / D30) | `retention` | | Measure what % of new users reach the first value moment | `activation` | | Identify users who have gone silent and are at churn risk | `churn` | | Know what fraction of active users have tried a feature | `featureAdoption` | | Detect unusual spikes or dips vs. a statistical baseline | `anomaly` | | Compute a simple A → B conversion rate | `conversion` | | Compare a metric across cohorts defined by join date or tier | `cohort` | | Plot event counts or unique users per time period | `trend` | See [Analysis Types](/docs/angular/concepts/insight_trackers/analysis_types) for the full reference for each type. # Tracker Repositories (/docs/angular/concepts/insight_trackers/tracker_repositories) Tracker location [#tracker-location] As a best practice, it is recommended to use a Git repository to store your trackers. You can connect a repository to your application instance to deploy and manage your trackers. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. Your tracker yaml files should be in the `.journium/trackers` directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker yaml files should be in the `https://github.com/my-org/my-repo/.journium/trackers` directory. Recommended Layout [#recommended-layout] You can colocate your trackers in your source code repository (recommended) or in a seperate repository as well. Here's how your repository should look like for the best practice: Linking a Git Repository [#linking-a-git-repository] Follw the steps below to to link a git repository containing tracker yaml files to your application instance.
Connect Git Account [#connect-git-account] To link a repository, you need to have a Git integration configured in Journium. You can configure a Git integration at [Integrations | Git](https://dashboard.journium.app/integrations/git) by connecting your GitHub account. For other Git providers, drop us a note at [support@journium.app](mailto:support@journium.app). The GitHub App for Journium is used to connect your GitHub repositories to your application instance. You can provide permissions to the specific repositories you want to connect to your application instance. Link Repository [#link-repository] After you have configured a Git integration, you can link a repository to your application instance. View Deployment History [#view-deployment-history] Navigate to the Tracker Repositories page to view the deployment history of your trackers. When you push changes to the deployment branch, the trackers will be synced to your application instance. This is called a deployment. Files are deployed to the application instance only if the YAML is valid.
# Tracker Specification (/docs/angular/concepts/insight_trackers/tracker_specification) A Journium InsightTracker is defined using a structured YAML format that follows the [InsightTracker schema](https://journium.app/schemas/journium-insight-tracker.schema.json). Top-Level Properties [#top-level-properties] metadata Properties [#metadata-properties] spec Properties [#spec-properties] trigger Properties [#trigger-properties] " }`', required: false, }, }} /> window Properties [#window-properties] ", end: "" }`', required: true, }, granularity: { description: 'Optional time-bucket size for time-series analysis types (trend, anomaly). Ignored by non-time-series types.', type: 'string', typeDescription: '`"hour"` | `"day"` | `"week"` | `"month"`', required: false, }, timezone: { description: 'Optional IANA timezone used when bucketing time-series data. Defaults to UTC.', type: 'string', typeDescription: 'e.g. `"America/New_York"`, `"Europe/London"`', required: false, }, }} /> *** Shared Primitives [#shared-primitives] These types are referenced by multiple analysis configurations. PropertyFilter [#propertyfilter] Used to narrow the set of events considered by an analysis step. BreakdownDef [#breakdowndef] Segments analysis results by a property dimension. *** Analysis Types [#analysis-types] The `analysis.type` field selects the analysis algorithm. Each type computes different metrics and injects different template variables into your `llm.promptTemplate`. | Type | Description | | ------------------------------------------------------ | ---------------------------------------------------------- | | [`funnel`](./analysis_types/funnel) | Ordered step completion — find where users drop off | | [`retention`](./analysis_types/retention) | Cohort return-rate curves (D1 / D7 / D30) | | [`activation`](./analysis_types/activation) | % of new users who reach the first value moment | | [`churn`](./analysis_types/churn) | Users who were active but have gone silent | | [`featureAdoption`](./analysis_types/feature_adoption) | Fraction of active users who have tried a feature | | [`anomaly`](./analysis_types/anomaly) | Automated spike / dip detection vs. a statistical baseline | | [`conversion`](./analysis_types/conversion) | Simple numerator / denominator conversion rate | | [`cohort`](./analysis_types/cohort) | Compare a metric across cohorts by join date or property | | [`trend`](./analysis_types/trend) | Count events or unique users per time period | | [`custom`](./analysis_types/custom) | Raw event list analysis — not available in the NL Builder | See the [Analysis Types overview](./analysis_types) for per-type configuration reference and examples. *** llm Properties [#llm-properties] Universal Template Variables [#universal-template-variables] These variables are always available in `promptTemplate`, regardless of analysis type: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result from the analysis query, serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Type-specific variables are documented on each analysis type's reference page. *** privacy Properties [#privacy-properties] *** Full Example [#full-example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day timezone: America/New_York analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel with an overall conversion of {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst performing step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 concrete, actionable recommendations to improve conversion. maxOutputTokens: 500 guardrails: citeSources: true privacy: excludeProperties: - email - phone hashProperties: - userId ``` # Creating Insight Trackers (/docs/js/concepts/insight_trackers/creating_trackers) Trackers can be created in three ways. The **NL Builder** lets you describe what you want to track in plain English and generates a fully-configured tracker for you. The **YAML Editor** gives you direct control over the tracker specification. **Git Repository** sync lets you version control your tracker files and deploy them automatically on push. Irrespective of the method you use, the result is always a YAML tracker specification file that you can inspect and edit at any time. Trackers are specific to an application instance. Trackers configured for one application instance are not shared with other instances. Describe in English (NL Builder) [#describe-in-english-nl-builder] The NL Builder is the fastest way to create a new tracker. Describe what you want to measure in plain English — Journium's AI assistant will choose the right analysis type, configure the fields, and generate a complete tracker spec for you. You can access the NL Builder from [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) by selecting the **Describe in English** option. The NL Builder walks you through four steps: 1. Describe Your Goal [#1-describe-your-goal] Type a natural-language description of the insight you want. Be as specific as you like — include event names, time windows, and any segmentation properties you care about. Examples: * *"Track how many users drop off during checkout — from cart viewed through order completed, broken down by plan."* * *"Show me 30-day retention after signup, with weekly cohort groups."* * *"Alert me when error event rates spike more than 2 standard deviations above the 14-day rolling average."* 2. Clarify (if needed) [#2-clarify-if-needed] If your description is ambiguous, Journium may ask a small number of clarifying questions (e.g. which events to treat as the start and end of an activation window). Answer them in the same text field — the builder will update its draft accordingly. 3. Review the Draft [#3-review-the-draft] Once the pipeline completes, you'll see a full YAML tracker spec in the editor along with **instrumentation notes** — a checklist of any new events or properties your tracker requires that haven't been seen in your app yet. Review the spec, make any manual adjustments in the YAML editor, and decide on a status: * **Save as Draft** — saves the tracker in draft status (no scheduled runs) * **Save & Activate** — saves and activates the tracker immediately 4. Instrument Your Events (if required) [#4-instrument-your-events-if-required] If the instrumentation notes list events or properties your app doesn't currently send, follow the instrumentation guide for your SDK to start capturing them before activating the tracker. **Test Data**: The NL Builder also generates a sample test-events file (downloadable from the tracker detail page) so you can verify the tracker's analysis logic before real events arrive. Using YAML Editor [#using-yaml-editor] You can create a new tracker manually using the tracker specification YAML. This gives you full control over every configuration field. Go to [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) and choose the **Use YAML Editor** option. The editor is pre-filled with a sample tracker specification. Edit the YAML to match your requirements. The editor provides a validation status badge to indicate the validity of the YAML. If errors exist, they are shown in the gutter. Hover over the error to see the message. You can save only when the YAML is valid. Example YAML [#example-yaml] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Data: {{dataAsJson}} Give 2-3 concrete optimization recommendations. maxOutputTokens: 500 ``` See the [Tracker Specification](/docs/concepts/insight_trackers/tracker_specification) reference for the complete list of fields. Best Practices [#best-practices] When authoring tracker YAML directly: 1. **Choose the right analysis type**: Match the `analysis.type` to the question you're asking — see [Analysis Types](/docs/concepts/insight_trackers/analysis_types) for guidance 2. **Use only valid template variables**: Each analysis type exposes a specific set of `{{variables}}` — using an unsupported variable will be rejected at save time 3. **Set appropriate schedules**: Use `automatic` with a `schedule` for continuous monitoring; use `manual` for exploratory or ad-hoc analysis 4. **Keep prompts focused**: One clear question per tracker produces better insights than an open-ended catch-all prompt 5. **Use `privacy` to protect PII**: List any user-identifying properties in `excludeProperties` or `hashProperties` **Default Tracker**: When you create an app in Journium, a default "User Engagement" tracker is automatically created. This tracker helps you test data ingestion and insight generation with your initial events. From Git Repository [#from-git-repository] You can connect a repository to your application instance at [Developers | Insight Trackers | Link Git Repository](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new/git). Tracker files from your git repository will be synced to your application instance. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. **Note**: Your tracker YAML files should be in the .journium/trackers directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker YAML files should be at `https://github.com/my-org/my-repo/tree/main/.journium/trackers`. # Insight Trackers (/docs/js/concepts/insight_trackers) An Insight Tracker in Journium is a declarative configuration that tells Journium what to analyze and how often. It acts as a bridge between your raw [Events](/docs/js/concepts/events) and the [Insights](/docs/js/concepts/insights) that help you understand your application's behavior. What are Insight Trackers? [#what-are-insight-trackers] Insight Trackers are the core of Journium's **Insights as Code** approach. Instead of manually querying data or building dashboards, you define what you want to know about your application, and Journium's AI-driven analytics engine automatically analyzes your event data to generate concise, actionable insights. Think of an Insight Tracker as a continuous data analyst that: * Runs a **structured analysis** against your events (funnel, retention, churn, trend, and more) * Synthesizes findings into a natural-language insight using an LLM with your custom prompt * Runs automatically on a schedule or on-demand * Surfaces results on your application's Insights page Each tracker's `analysis` block selects one of nine structured analysis types — covering funnel drop-off, cohort retention, activation rates, churn risk, feature adoption, anomaly detection, conversion rates, cohort comparisons, and trend/growth analysis. This structured approach replaces freeform raw-event queries and produces higher-quality, more consistent insights. How Insight Trackers Work [#how-insight-trackers-work] Insight Trackers transform raw telemetry data into human-readable insights through an AI-driven pipeline: 1. **Query Compilation**: Journium compiles your `analysis` config into optimised analytical queries for the chosen `window` period 2. **Data Retrieval**: The compiled queries run against your event data and return structured results (conversion rates, cohort tables, anomaly scores, etc.) 3. **Payload Building**: The structured results are mapped to named template variables and injected into your `llm.promptTemplate` 4. **Insight Generation**: The LLM synthesises the data into a concise, natural-language insight backed by verifiable numbers 5. **Delivery**: Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page This process eliminates the need for manual data exploration, SQL queries, or dashboard interpretation. You can list an application instance's insight trackers at [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) from your application instance page. Choosing an Analysis Type [#choosing-an-analysis-type] The `analysis.type` field determines what Journium computes and which template variables are available in your prompt. Choose the type that best matches the question you want to answer: | If you want to… | Use type | | ------------------------------------------------------------ | ----------------- | | See where users drop off across ordered steps | `funnel` | | Track cohort return rates over time (D1 / D7 / D30) | `retention` | | Measure what % of new users reach the first value moment | `activation` | | Identify users who have gone silent and are at churn risk | `churn` | | Know what fraction of active users have tried a feature | `featureAdoption` | | Detect unusual spikes or dips vs. a statistical baseline | `anomaly` | | Compute a simple A → B conversion rate | `conversion` | | Compare a metric across cohorts defined by join date or tier | `cohort` | | Plot event counts or unique users per time period | `trend` | See [Analysis Types](/docs/js/concepts/insight_trackers/analysis_types) for the full reference for each type. # Tracker Repositories (/docs/js/concepts/insight_trackers/tracker_repositories) Tracker location [#tracker-location] As a best practice, it is recommended to use a Git repository to store your trackers. You can connect a repository to your application instance to deploy and manage your trackers. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. Your tracker yaml files should be in the `.journium/trackers` directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker yaml files should be in the `https://github.com/my-org/my-repo/.journium/trackers` directory. Recommended Layout [#recommended-layout] You can colocate your trackers in your source code repository (recommended) or in a seperate repository as well. Here's how your repository should look like for the best practice: Linking a Git Repository [#linking-a-git-repository] Follw the steps below to to link a git repository containing tracker yaml files to your application instance.
Connect Git Account [#connect-git-account] To link a repository, you need to have a Git integration configured in Journium. You can configure a Git integration at [Integrations | Git](https://dashboard.journium.app/integrations/git) by connecting your GitHub account. For other Git providers, drop us a note at [support@journium.app](mailto:support@journium.app). The GitHub App for Journium is used to connect your GitHub repositories to your application instance. You can provide permissions to the specific repositories you want to connect to your application instance. Link Repository [#link-repository] After you have configured a Git integration, you can link a repository to your application instance. View Deployment History [#view-deployment-history] Navigate to the Tracker Repositories page to view the deployment history of your trackers. When you push changes to the deployment branch, the trackers will be synced to your application instance. This is called a deployment. Files are deployed to the application instance only if the YAML is valid.
# Tracker Specification (/docs/js/concepts/insight_trackers/tracker_specification) A Journium InsightTracker is defined using a structured YAML format that follows the [InsightTracker schema](https://journium.app/schemas/journium-insight-tracker.schema.json). Top-Level Properties [#top-level-properties] metadata Properties [#metadata-properties] spec Properties [#spec-properties] trigger Properties [#trigger-properties] " }`', required: false, }, }} /> window Properties [#window-properties] ", end: "" }`', required: true, }, granularity: { description: 'Optional time-bucket size for time-series analysis types (trend, anomaly). Ignored by non-time-series types.', type: 'string', typeDescription: '`"hour"` | `"day"` | `"week"` | `"month"`', required: false, }, timezone: { description: 'Optional IANA timezone used when bucketing time-series data. Defaults to UTC.', type: 'string', typeDescription: 'e.g. `"America/New_York"`, `"Europe/London"`', required: false, }, }} /> *** Shared Primitives [#shared-primitives] These types are referenced by multiple analysis configurations. PropertyFilter [#propertyfilter] Used to narrow the set of events considered by an analysis step. BreakdownDef [#breakdowndef] Segments analysis results by a property dimension. *** Analysis Types [#analysis-types] The `analysis.type` field selects the analysis algorithm. Each type computes different metrics and injects different template variables into your `llm.promptTemplate`. | Type | Description | | ------------------------------------------------------ | ---------------------------------------------------------- | | [`funnel`](./analysis_types/funnel) | Ordered step completion — find where users drop off | | [`retention`](./analysis_types/retention) | Cohort return-rate curves (D1 / D7 / D30) | | [`activation`](./analysis_types/activation) | % of new users who reach the first value moment | | [`churn`](./analysis_types/churn) | Users who were active but have gone silent | | [`featureAdoption`](./analysis_types/feature_adoption) | Fraction of active users who have tried a feature | | [`anomaly`](./analysis_types/anomaly) | Automated spike / dip detection vs. a statistical baseline | | [`conversion`](./analysis_types/conversion) | Simple numerator / denominator conversion rate | | [`cohort`](./analysis_types/cohort) | Compare a metric across cohorts by join date or property | | [`trend`](./analysis_types/trend) | Count events or unique users per time period | | [`custom`](./analysis_types/custom) | Raw event list analysis — not available in the NL Builder | See the [Analysis Types overview](./analysis_types) for per-type configuration reference and examples. *** llm Properties [#llm-properties] Universal Template Variables [#universal-template-variables] These variables are always available in `promptTemplate`, regardless of analysis type: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result from the analysis query, serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Type-specific variables are documented on each analysis type's reference page. *** privacy Properties [#privacy-properties] *** Full Example [#full-example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day timezone: America/New_York analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel with an overall conversion of {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst performing step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 concrete, actionable recommendations to improve conversion. maxOutputTokens: 500 guardrails: citeSources: true privacy: excludeProperties: - email - phone hashProperties: - userId ``` # Creating Insight Trackers (/docs/react/concepts/insight_trackers/creating_trackers) Trackers can be created in three ways. The **NL Builder** lets you describe what you want to track in plain English and generates a fully-configured tracker for you. The **YAML Editor** gives you direct control over the tracker specification. **Git Repository** sync lets you version control your tracker files and deploy them automatically on push. Irrespective of the method you use, the result is always a YAML tracker specification file that you can inspect and edit at any time. Trackers are specific to an application instance. Trackers configured for one application instance are not shared with other instances. Describe in English (NL Builder) [#describe-in-english-nl-builder] The NL Builder is the fastest way to create a new tracker. Describe what you want to measure in plain English — Journium's AI assistant will choose the right analysis type, configure the fields, and generate a complete tracker spec for you. You can access the NL Builder from [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) by selecting the **Describe in English** option. The NL Builder walks you through four steps: 1. Describe Your Goal [#1-describe-your-goal] Type a natural-language description of the insight you want. Be as specific as you like — include event names, time windows, and any segmentation properties you care about. Examples: * *"Track how many users drop off during checkout — from cart viewed through order completed, broken down by plan."* * *"Show me 30-day retention after signup, with weekly cohort groups."* * *"Alert me when error event rates spike more than 2 standard deviations above the 14-day rolling average."* 2. Clarify (if needed) [#2-clarify-if-needed] If your description is ambiguous, Journium may ask a small number of clarifying questions (e.g. which events to treat as the start and end of an activation window). Answer them in the same text field — the builder will update its draft accordingly. 3. Review the Draft [#3-review-the-draft] Once the pipeline completes, you'll see a full YAML tracker spec in the editor along with **instrumentation notes** — a checklist of any new events or properties your tracker requires that haven't been seen in your app yet. Review the spec, make any manual adjustments in the YAML editor, and decide on a status: * **Save as Draft** — saves the tracker in draft status (no scheduled runs) * **Save & Activate** — saves and activates the tracker immediately 4. Instrument Your Events (if required) [#4-instrument-your-events-if-required] If the instrumentation notes list events or properties your app doesn't currently send, follow the instrumentation guide for your SDK to start capturing them before activating the tracker. **Test Data**: The NL Builder also generates a sample test-events file (downloadable from the tracker detail page) so you can verify the tracker's analysis logic before real events arrive. Using YAML Editor [#using-yaml-editor] You can create a new tracker manually using the tracker specification YAML. This gives you full control over every configuration field. Go to [Developers | Insight Trackers | Create New](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new) and choose the **Use YAML Editor** option. The editor is pre-filled with a sample tracker specification. Edit the YAML to match your requirements. The editor provides a validation status badge to indicate the validity of the YAML. If errors exist, they are shown in the gutter. Hover over the error to see the message. You can save only when the YAML is valid. Example YAML [#example-yaml] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Data: {{dataAsJson}} Give 2-3 concrete optimization recommendations. maxOutputTokens: 500 ``` See the [Tracker Specification](/docs/concepts/insight_trackers/tracker_specification) reference for the complete list of fields. Best Practices [#best-practices] When authoring tracker YAML directly: 1. **Choose the right analysis type**: Match the `analysis.type` to the question you're asking — see [Analysis Types](/docs/concepts/insight_trackers/analysis_types) for guidance 2. **Use only valid template variables**: Each analysis type exposes a specific set of `{{variables}}` — using an unsupported variable will be rejected at save time 3. **Set appropriate schedules**: Use `automatic` with a `schedule` for continuous monitoring; use `manual` for exploratory or ad-hoc analysis 4. **Keep prompts focused**: One clear question per tracker produces better insights than an open-ended catch-all prompt 5. **Use `privacy` to protect PII**: List any user-identifying properties in `excludeProperties` or `hashProperties` **Default Tracker**: When you create an app in Journium, a default "User Engagement" tracker is automatically created. This tracker helps you test data ingestion and insight generation with your initial events. From Git Repository [#from-git-repository] You can connect a repository to your application instance at [Developers | Insight Trackers | Link Git Repository](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers/new/git). Tracker files from your git repository will be synced to your application instance. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. **Note**: Your tracker YAML files should be in the .journium/trackers directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker YAML files should be at `https://github.com/my-org/my-repo/tree/main/.journium/trackers`. # Insight Trackers (/docs/react/concepts/insight_trackers) An Insight Tracker in Journium is a declarative configuration that tells Journium what to analyze and how often. It acts as a bridge between your raw [Events](/docs/react/concepts/events) and the [Insights](/docs/react/concepts/insights) that help you understand your application's behavior. What are Insight Trackers? [#what-are-insight-trackers] Insight Trackers are the core of Journium's **Insights as Code** approach. Instead of manually querying data or building dashboards, you define what you want to know about your application, and Journium's AI-driven analytics engine automatically analyzes your event data to generate concise, actionable insights. Think of an Insight Tracker as a continuous data analyst that: * Runs a **structured analysis** against your events (funnel, retention, churn, trend, and more) * Synthesizes findings into a natural-language insight using an LLM with your custom prompt * Runs automatically on a schedule or on-demand * Surfaces results on your application's Insights page Each tracker's `analysis` block selects one of nine structured analysis types — covering funnel drop-off, cohort retention, activation rates, churn risk, feature adoption, anomaly detection, conversion rates, cohort comparisons, and trend/growth analysis. This structured approach replaces freeform raw-event queries and produces higher-quality, more consistent insights. How Insight Trackers Work [#how-insight-trackers-work] Insight Trackers transform raw telemetry data into human-readable insights through an AI-driven pipeline: 1. **Query Compilation**: Journium compiles your `analysis` config into optimised analytical queries for the chosen `window` period 2. **Data Retrieval**: The compiled queries run against your event data and return structured results (conversion rates, cohort tables, anomaly scores, etc.) 3. **Payload Building**: The structured results are mapped to named template variables and injected into your `llm.promptTemplate` 4. **Insight Generation**: The LLM synthesises the data into a concise, natural-language insight backed by verifiable numbers 5. **Delivery**: Insights appear on your application instance's [Insights](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/insights) page This process eliminates the need for manual data exploration, SQL queries, or dashboard interpretation. You can list an application instance's insight trackers at [Developers | Insight Trackers](https://dashboard.journium.app/apps/j_app~/instances/j_app_inst~/developers/insight-trackers) from your application instance page. Choosing an Analysis Type [#choosing-an-analysis-type] The `analysis.type` field determines what Journium computes and which template variables are available in your prompt. Choose the type that best matches the question you want to answer: | If you want to… | Use type | | ------------------------------------------------------------ | ----------------- | | See where users drop off across ordered steps | `funnel` | | Track cohort return rates over time (D1 / D7 / D30) | `retention` | | Measure what % of new users reach the first value moment | `activation` | | Identify users who have gone silent and are at churn risk | `churn` | | Know what fraction of active users have tried a feature | `featureAdoption` | | Detect unusual spikes or dips vs. a statistical baseline | `anomaly` | | Compute a simple A → B conversion rate | `conversion` | | Compare a metric across cohorts defined by join date or tier | `cohort` | | Plot event counts or unique users per time period | `trend` | See [Analysis Types](/docs/react/concepts/insight_trackers/analysis_types) for the full reference for each type. # Tracker Repositories (/docs/react/concepts/insight_trackers/tracker_repositories) Tracker location [#tracker-location] As a best practice, it is recommended to use a Git repository to store your trackers. You can connect a repository to your application instance to deploy and manage your trackers. When you push your changes to the deployment branch, the trackers will be synced to your application instance. You can select any branch as the deployment branch. By default, the deployment branch is the default branch of the repository. Your tracker yaml files should be in the `.journium/trackers` directory in your repository. For example, if your repository is `https://github.com/my-org/my-repo`, your tracker yaml files should be in the `https://github.com/my-org/my-repo/.journium/trackers` directory. Recommended Layout [#recommended-layout] You can colocate your trackers in your source code repository (recommended) or in a seperate repository as well. Here's how your repository should look like for the best practice: Linking a Git Repository [#linking-a-git-repository] Follw the steps below to to link a git repository containing tracker yaml files to your application instance.
Connect Git Account [#connect-git-account] To link a repository, you need to have a Git integration configured in Journium. You can configure a Git integration at [Integrations | Git](https://dashboard.journium.app/integrations/git) by connecting your GitHub account. For other Git providers, drop us a note at [support@journium.app](mailto:support@journium.app). The GitHub App for Journium is used to connect your GitHub repositories to your application instance. You can provide permissions to the specific repositories you want to connect to your application instance. Link Repository [#link-repository] After you have configured a Git integration, you can link a repository to your application instance. View Deployment History [#view-deployment-history] Navigate to the Tracker Repositories page to view the deployment history of your trackers. When you push changes to the deployment branch, the trackers will be synced to your application instance. This is called a deployment. Files are deployed to the application instance only if the YAML is valid.
# Tracker Specification (/docs/react/concepts/insight_trackers/tracker_specification) A Journium InsightTracker is defined using a structured YAML format that follows the [InsightTracker schema](https://journium.app/schemas/journium-insight-tracker.schema.json). Top-Level Properties [#top-level-properties] metadata Properties [#metadata-properties] spec Properties [#spec-properties] trigger Properties [#trigger-properties] " }`', required: false, }, }} /> window Properties [#window-properties] ", end: "" }`', required: true, }, granularity: { description: 'Optional time-bucket size for time-series analysis types (trend, anomaly). Ignored by non-time-series types.', type: 'string', typeDescription: '`"hour"` | `"day"` | `"week"` | `"month"`', required: false, }, timezone: { description: 'Optional IANA timezone used when bucketing time-series data. Defaults to UTC.', type: 'string', typeDescription: 'e.g. `"America/New_York"`, `"Europe/London"`', required: false, }, }} /> *** Shared Primitives [#shared-primitives] These types are referenced by multiple analysis configurations. PropertyFilter [#propertyfilter] Used to narrow the set of events considered by an analysis step. BreakdownDef [#breakdowndef] Segments analysis results by a property dimension. *** Analysis Types [#analysis-types] The `analysis.type` field selects the analysis algorithm. Each type computes different metrics and injects different template variables into your `llm.promptTemplate`. | Type | Description | | ------------------------------------------------------ | ---------------------------------------------------------- | | [`funnel`](./analysis_types/funnel) | Ordered step completion — find where users drop off | | [`retention`](./analysis_types/retention) | Cohort return-rate curves (D1 / D7 / D30) | | [`activation`](./analysis_types/activation) | % of new users who reach the first value moment | | [`churn`](./analysis_types/churn) | Users who were active but have gone silent | | [`featureAdoption`](./analysis_types/feature_adoption) | Fraction of active users who have tried a feature | | [`anomaly`](./analysis_types/anomaly) | Automated spike / dip detection vs. a statistical baseline | | [`conversion`](./analysis_types/conversion) | Simple numerator / denominator conversion rate | | [`cohort`](./analysis_types/cohort) | Compare a metric across cohorts by join date or property | | [`trend`](./analysis_types/trend) | Count events or unique users per time period | | [`custom`](./analysis_types/custom) | Raw event list analysis — not available in the NL Builder | See the [Analysis Types overview](./analysis_types) for per-type configuration reference and examples. *** llm Properties [#llm-properties] Universal Template Variables [#universal-template-variables] These variables are always available in `promptTemplate`, regardless of analysis type: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result from the analysis query, serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Type-specific variables are documented on each analysis type's reference page. *** privacy Properties [#privacy-properties] *** Full Example [#full-example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d granularity: day timezone: America/New_York analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel with an overall conversion of {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst performing step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 concrete, actionable recommendations to improve conversion. maxOutputTokens: 500 guardrails: citeSources: true privacy: excludeProperties: - email - phone hashProperties: - userId ``` # Activation Analysis (/docs/concepts/insight_trackers/analysis_types/activation) Overview [#overview] Activation Analysis measures the "aha moment" rate — what percentage of users who completed a start event (e.g., signed up) also completed a key value action within a defined time window. It tells you how effective your onboarding is at guiding new users to first value. **When to use activation**: "What % of signups create a project within 24 hours?", "Are new users finding value quickly enough?", "What is our activation rate for trial users?" — any question about the rate at which new users reach a meaningful milestone. **When NOT to use activation**: If you want historical cohort return-rate curves, use [`retention`](./retention). If you want to identify currently inactive users, use [`churn`](./churn). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{newUsers}}` | Number of users who fired `startEvent` in the window | | `{{activated}}` | Number of users who also fired `ahaEvent` within `activationWindow` | | `{{activationRatePct}}` | Percentage of new users who activated | | `{{avgHoursToAha}}` | Average hours from `startEvent` to `ahaEvent` for activated users | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevActivationRatePct}}` | Activation rate in the previous period (when `hasComparison` is true) | | `{{activationDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-to-project.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-to-project displayName: Signup → First Project (24h Activation) description: What % of new signups create a project within 24 hours spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d analysis: type: activation entity: person_id startEvent: user_signed_up ahaEvent: project_created activationWindow: 24h compareWindow: previous_period llm: promptTemplate: | Analyze activation for {{windowPeriod}}. {{newUsers}} new users signed up. {{activated}} activated ({{activationRatePct}}%). Average time to aha moment: {{avgHoursToAha}} hours. {{#if hasComparison}} Previous period activation: {{prevActivationRatePct}}% ({{activationDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the biggest friction points preventing activation and suggest one targeted fix. maxOutputTokens: 400 ``` # Anomaly Detection (/docs/concepts/insight_trackers/analysis_types/anomaly) Overview [#overview] Anomaly Detection automatically identifies unusual spikes or dips in a metric compared to a statistical baseline. This is alert-mode, not view-mode — the LLM is told **what deviated and by how much**, rather than being asked to interpret a time series. Use it for automatic monitoring of key metrics where you want to be notified when something unusual happens. **When to use anomaly**: "Alert me when error rates spike", "Did anything unusual happen with revenue this week?", "Detect and explain anomalies in daily active users." **When NOT to use anomaly**: If you want to *view* a time-series trend without automated detection, use [`trend`](./trend). If you want step-by-step drop-off analysis, use [`funnel`](./funnel). Configuration Reference [#configuration-reference] AnomalyMetricDef Properties [#anomalymetricdef-properties] AnomalyBaseline — type values [#anomalybaseline--type-values] | Value | Meaning | | -------------------------- | ----------------------------------------------------- | | `"rolling_average"` | Average of the metric over the last `windowDays` days | | `"same_period_last_week"` | Same time period from the previous week | | `"same_period_last_month"` | Same time period from the previous month | Available Template Variables [#available-template-variables] | Variable | Description | | -------------------- | ------------------------------------------------------------------------- | | `{{metricCount}}` | Number of metrics being monitored | | `{{totalAnomalies}}` | Total number of anomalous time buckets detected across all metrics | | `{{anomalySummary}}` | Per-metric anomaly details (metric label, deviation magnitude, direction) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/error-rate-anomaly.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: error-rate-anomaly displayName: Error Rate Anomaly Detection description: Alert when error event rates spike above statistical normal spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d granularity: hour analysis: type: anomaly metrics: - event: error_occurred aggregation: count groupBy: hour label: Error Rate - event: api_call_failed aggregation: count groupBy: hour label: API Failure Rate baseline: type: rolling_average windowDays: 14 threshold: stdDeviations: 2.5 minAbsoluteChange: 10 includeTimeSeries: false llm: promptTemplate: | Error monitoring report for {{windowPeriod}}. {{metricCount}} metrics monitored. {{totalAnomalies}} anomalous periods detected. Anomaly summary: {{anomalySummary}} Full data: {{dataAsJson}} Describe the most significant anomaly, its likely cause, and recommended response. maxOutputTokens: 500 ``` # Churn Risk Analysis (/docs/concepts/insight_trackers/analysis_types/churn) Overview [#overview] Churn Risk Analysis finds users who were active during a lookback period but have not performed any qualifying activity within the inactivity threshold. These users are flagged as "at churn risk". The analysis gives you an actionable count today — not a historical trend. **When to use churn**: "Which users haven't logged in for 2 weeks?", "How many active users are at churn risk right now?", "Who do I need to reach out to before they leave?" — any question about currently at-risk users. **When NOT to use churn**: If you want historical retention trend curves over cohorts, use [`retention`](./retention). If you want a time-series activity count, use [`trend`](./trend). Configuration Reference [#configuration-reference] activeEvent values [#activeevent-values] | Value | Meaning | | --------------------------------- | ---------------------------------------------- | | `"*"` | Any event fired by the user counts as activity | | `"session_started"` | Only this specific event counts as activity | | `["session_started", "api_call"]` | Any event in this list counts as activity | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ------------------------------------------------------------------- | | `{{activeBase}}` | Total number of users who were active during the lookback period | | `{{atRiskCount}}` | Number of users currently at churn risk | | `{{atRiskRatePct}}` | Percentage of the active base that is at churn risk | | `{{churnSummary}}` | Segment breakdown of at-risk users (when `segments` are configured) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/churn-risk-14d.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: churn-risk-14d displayName: Churn Risk (14-day Inactivity) description: Users who were active in the last 90 days but silent for 14+ days spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d analysis: type: churn entity: person_id activeEvent: session_started inactivityThreshold: 14d lookbackPeriod: 90d segments: - property: plan metrics: - atRiskCount - atRiskRate - segmentBreakdown llm: promptTemplate: | Churn risk analysis for {{windowPeriod}}. Active user base: {{activeBase}}. At-risk users: {{atRiskCount}} ({{atRiskRatePct}}%). Segment breakdown: {{churnSummary}} Full data: {{dataAsJson}} Summarize the churn risk situation and recommend one re-engagement action. maxOutputTokens: 400 ``` # Cohort Analysis (/docs/concepts/insight_trackers/analysis_types/cohort) Overview [#overview] Cohort Analysis groups users into cohorts — either by **when they first did something** (time-based) or by a **static property value** (e.g. plan tier) — and then compares a metric across those cohorts. Use it to answer "do users who joined in January behave differently to February signups?" or "how does purchase frequency differ across plan tiers?" **When to use cohort**: "Do users who signed up in January spend more than February signups?", "Compare engagement by plan tier", "Show LTV curves by acquisition month." **When NOT to use cohort**: If you want period-by-period return rates for a single cohort, use [`retention`](./retention). If you want a plain time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] CohortByFirstEvent Properties [#cohortbyfirstevent-properties] Groups users by the calendar period of their first occurrence of a specific event. CohortByProperty Properties [#cohortbyproperty-properties] Groups users by a static event property value (e.g. their plan at signup). CohortAggregation values [#cohortaggregation-values] | Value | Meaning | | --------------- | ------------------------------------------------------------ | | `"count"` | Total event occurrences in the cohort | | `"uniqueUsers"` | Unique users in the cohort who fired the metric event | | `"avg"` | Average value of a numeric property (requires `sumProperty`) | | `"sum"` | Sum of a numeric property (requires `sumProperty`) | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ---------------------------------------------------------- | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{avgCohortSize}}` | Average number of users per cohort | | `{{cohortSummary}}` | Per-cohort metric table (cohort label, size, metric value) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/weekly-cohort-purchases.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: weekly-cohort-purchases displayName: Weekly Signup Cohort → Purchase Comparison description: Compare purchase rates across weekly signup cohorts spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: cohort entity: person_id cohortDefinition: firstEvent: user_signed_up period: week metric: event: purchase_completed aggregation: uniqueUsers maxCohorts: 12 llm: promptTemplate: | Weekly cohort analysis for {{windowPeriod}}. {{cohortCount}} cohorts included. Average cohort size: {{avgCohortSize}} users. Cohort comparison: {{cohortSummary}} Full data: {{dataAsJson}} Identify which signup cohorts have the highest purchase rates and what might explain the difference. maxOutputTokens: 400 ``` # Conversion Rate (/docs/concepts/insight_trackers/analysis_types/conversion) Overview [#overview] Conversion Rate computes a simple two-event rate: what percentage of users who performed event A also performed event B within the analysis window. This is a single ratio — there are no intermediate steps and no drop-off ordering. Use it for binary conversion questions. **When to use conversion**: "What is our trial-to-paid conversion rate?", "What % of visitors sign up?", "What is the lead-to-close rate in the last 30 days?" **When NOT to use conversion**: If you need 3 or more ordered steps with intermediate drop-off analysis, use [`funnel`](./funnel). If you want a time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{denominatorCount}}` | Number of users who fired `denominatorEvent` in the window | | `{{numeratorCount}}` | Number of those users who also fired `numeratorEvent` | | `{{conversionRatePct}}` | Conversion rate as a percentage | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevConversionRatePct}}` | Conversion rate in the previous period (when `hasComparison` is true) | | `{{conversionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/trial-to-paid.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: trial-to-paid displayName: Trial → Paid Conversion Rate description: Percentage of trial starts that convert to a paid subscription within 30 days spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: conversion entity: person_id denominatorEvent: trial_started numeratorEvent: subscription_started conversionWindow: 30d breakdowns: - property: plan maxCardinality: 5 compareWindow: previous_period llm: promptTemplate: | Trial-to-paid conversion for {{windowPeriod}}. {{denominatorCount}} trials started. {{numeratorCount}} converted ({{conversionRatePct}}%). {{#if hasComparison}} Previous period: {{prevConversionRatePct}}% ({{conversionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the primary driver of the conversion rate and recommend one improvement. maxOutputTokens: 400 ``` # Custom Analysis (/docs/concepts/insight_trackers/analysis_types/custom) Custom analysis is not available in the AI-assisted tracker builder. Create custom trackers using the YAML editor. Overview [#overview] The `custom` analysis type passes a filtered list of raw events directly to the LLM for freeform analysis. Unlike structured types, it does not run pre-computed queries or inject metric variables — only the matching events and universal base variables are available. Use `custom` when none of the structured types fit your use case. Configuration Reference [#configuration-reference] RawEventsConfig Properties [#raweventsconfig-properties] Available Template Variables [#available-template-variables] `custom` analysis only has access to the universal base variables — no pre-computed metrics: | Variable | Description | | ------------------ | ---------------------------------------------------- | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Raw event list serialised as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/user-engagement.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: user-engagement displayName: User Engagement description: Tracks engagement patterns via raw event inspection spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: custom rawEvents: events: - signup_completed - habit_created - session_started minEvents: 1 maxEvents: 50 llm: promptTemplate: | Analyze user engagement for {{windowPeriod}}. Event data: {{dataAsJson}} Generate a one-sentence insight summarizing engagement patterns. maxOutputTokens: 200 ``` # Feature Adoption (/docs/concepts/insight_trackers/analysis_types/feature_adoption) Overview [#overview] Feature Adoption measures what percentage of your **active users** have tried a specific feature at least once during the analysis window. The adoption rate is `unique feature users ÷ total active users in the period`. This is distinct from a raw usage count — it tells you about feature discovery and uptake relative to your active user base. **When to use featureAdoption**: "How many active users have tried the new AI assistant?", "What is the adoption rate of the export feature?", "Is v2 dashboard adoption growing month over month?" **When NOT to use featureAdoption**: If you want a raw time-series count of feature usage, use [`trend`](./trend). If you want a simple rate not tied to the active user base, use [`conversion`](./conversion). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | -------------------------------------------------------------------------- | | `{{activeBaseCount}}` | Total active users in the analysis window | | `{{uniqueAdopters}}` | Users who fired at least one feature event | | `{{adoptionRatePct}}` | Percentage of active users who adopted the feature | | `{{avgUsesPerAdopter}}` | Average number of feature interactions per adopter | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevAdoptionRatePct}}` | Adoption rate in the previous period (when `hasComparison` is true) | | `{{adoptionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/ai-assistant-adoption.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: ai-assistant-adoption displayName: AI Assistant Feature Adoption description: What fraction of active users have tried the AI assistant spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: featureAdoption entity: person_id featureEvents: - event: ai_assistant_opened label: Opened AI Assistant - event: ai_suggestion_accepted label: Accepted AI Suggestion activeUserBaseline: event: session_started period: 30d breakdowns: - property: plan maxCardinality: 5 metrics: - adoptionRate - avgUsesPerAdopter - weekOverWeekDelta compareWindow: previous_period llm: promptTemplate: | AI assistant adoption analysis for {{windowPeriod}}. Active user base: {{activeBaseCount}}. Adopters: {{uniqueAdopters}} ({{adoptionRatePct}}%). Average uses per adopter: {{avgUsesPerAdopter}}. {{#if hasComparison}} Previous period: {{prevAdoptionRatePct}}% ({{adoptionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Describe whether adoption is healthy and suggest one action to increase it. maxOutputTokens: 400 ``` # Funnel Analysis (/docs/concepts/insight_trackers/analysis_types/funnel) Overview [#overview] Funnel Analysis tracks how users progress through an **ordered series of steps** and shows exactly where they drop off. Use it whenever the key question is "how many users made it from step A to step B (to step C …)?" and you need to see intermediate drop-off at each stage. **When to use funnel**: Checkout flows, onboarding wizards, trial-to-paid flows, signup sequences, feature setup journeys — any multi-step process where order matters and drop-off location is the insight you care about. **When NOT to use funnel**: If you only need a single A → B rate without step ordering, use [`conversion`](./conversion). If you want a time-series count of step completions, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | -------------------------- | ------------------------------------------------------------------ | | `{{totalEntrants}}` | Number of users who completed the first funnel step | | `{{overallConversionPct}}` | Percentage of entrants who completed the final step | | `{{stepsSummary}}` | Step-by-step conversion table (label, count, CVR%) | | `{{worstStep}}` | Label of the step with the highest absolute user loss | | `{{worstStepCvr}}` | Conversion rate (%) at the worst step | | `{{worstStepLoss}}` | Number of users lost at the worst step | | `{{hasBreakdown}}` | `true` if breakdown data is present | | `{{breakdownSummary}}` | Breakdown results table (only present when `hasBreakdown` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 actionable recommendations to improve conversion at the weakest step. maxOutputTokens: 500 ``` # Analysis Types (/docs/concepts/insight_trackers/analysis_types) Journium trackers use a structured `analysis` block that selects one of nine structured analysis algorithms, plus Custom analysis. Each type determines: * **What queries are compiled** against your event data * **Which template variables** are injected into your `llm.promptTemplate` * **What computed metrics** are surfaced in the insight Choosing the Right Type [#choosing-the-right-type] }> Track ordered step completion and identify where users drop off. }> Cohort return-rate curves over time — D1, D7, D30, and beyond. }> Measure what percentage of new users reach the first value moment. }> Identify users who were active but have since gone silent. }> What fraction of active users have tried a specific feature. }> Automated spike and dip detection vs. a statistical baseline. }> Simple numerator / denominator rate — percentage of group A that does B. }> Compare a metric across cohorts defined by join date or a property value. }> Count events or unique users per time period — daily, weekly, monthly. }> Pass raw matching events to the LLM — not available in the NL Builder. Quick Selection Guide [#quick-selection-guide] | If you want to… | Use type | | ---------------------------------------------------------- | ----------------- | | See where users drop off across an ordered multi-step flow | `funnel` | | Track what fraction of cohorts return at D1 / D7 / D30 | `retention` | | Measure the aha-moment rate for new users | `activation` | | Find users who went quiet and are at risk of churning | `churn` | | Know what fraction of active users have adopted a feature | `featureAdoption` | | Get alerted when a metric spikes or dips anomalously | `anomaly` | | Compute a simple event-A-to-event-B conversion rate | `conversion` | | Compare engagement or revenue across cohort groups | `cohort` | | Plot event counts, DAU, or sums over time | `trend` | | Analyze matching events without pre-computed metrics | `custom` | Universal Template Variables [#universal-template-variables] All analysis types inject these variables into `llm.promptTemplate`: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured analysis result serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Each analysis type also provides its own type-specific variables. See the individual type pages for details. # Retention Analysis (/docs/concepts/insight_trackers/analysis_types/retention) Overview [#overview] Retention Analysis measures what fraction of users who first performed an action (e.g., signed up) came back and performed a retention event at specified intervals (Day 1, Day 7, Day 30, etc.). It groups users into cohorts by the period they first acted and plots return rates for each cohort. **When to use retention**: "Are users coming back?", "How sticky is the product?", "Show me D7 and D30 retention after signup" — any question about cohort-based return rates over time. **When NOT to use retention**: If you want to identify who is *currently* inactive or at risk today, use [`churn`](./churn). If you want to measure the first-value-moment rate for new users, use [`activation`](./activation). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ---------------------- | ------------------------------------------------------------------------------------------ | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{retentionSummary}}` | Cohort × interval retention matrix (cohort label, size, and return rates at each interval) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-retention.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-retention displayName: Signup Retention (D1 / D7 / D30) description: Weekly cohort retention after signup spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: retention entity: person_id cohortEvent: user_signed_up retentionEvent: session_started cohortPeriod: week intervals: [1, 7, 14, 30] minCohortSize: 20 maxCohorts: 12 llm: promptTemplate: | Analyze signup retention for {{windowPeriod}}. {{cohortCount}} weekly cohorts included. Retention matrix: {{retentionSummary}} Full data: {{dataAsJson}} Identify the cohorts with the best and worst D7 retention, and suggest one actionable improvement for early-session engagement. maxOutputTokens: 400 ``` # Trend / Growth (/docs/concepts/insight_trackers/analysis_types/trend) Overview [#overview] Trend Analysis computes a time-series of an aggregated metric bucketed by `hour`, `day`, `week`, or `month`. It covers all growth and usage-frequency questions. "How many times does X happen per period?" is always a trend question. **When to use trend**: "How many users are signing up every month?", "Show me daily active users over the last 90 days", "What is the weekly trend in purchases over the past quarter?" **When NOT to use trend**: If you want automated spike/dip alerts, use [`anomaly`](./anomaly). If you want cohort return curves, use [`retention`](./retention). If you want to compare groups, use [`cohort`](./cohort). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | ------------------------------------------------------------------------- | | `{{metricName}}` | Human-readable name for the metric (derived from `event` + `aggregation`) | | `{{periodCount}}` | Number of time buckets in the result | | `{{currentPeriodValue}}` | Value in the most recent complete time bucket | | `{{peakPeriod}}` | Label of the time bucket with the highest value | | `{{peakValue}}` | The value at the peak period | | `{{trendDirection}}` | Overall trend direction: `"up"`, `"down"`, or `"flat"` | | `{{trendSummary}}` | Human-readable summary of the trend (e.g. "grew 12% week-over-week") | | `{{hasComparison}}` | `true` if `compareWindow` data is available | | `{{previousPeriodValue}}` | Value in the equivalent previous period (when `hasComparison` is true) | | `{{growthRatePct}}` | Percentage change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/daily-signups-trend.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: daily-signups-trend displayName: Daily Signups Trend (WoW) description: Daily signup count with week-over-week comparison spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d granularity: day analysis: type: trend entity: person_id event: user_signed_up aggregation: uniqueUsers groupBy: day compareWindow: previous_period llm: promptTemplate: | Daily signup trend for {{windowPeriod}}. Metric: {{metricName}} — {{periodCount}} days. Most recent day: {{currentPeriodValue}} signups. Peak day: {{peakPeriod}} ({{peakValue}} signups). Overall trend: {{trendDirection}}. {{trendSummary}} {{#if hasComparison}} Previous period: {{previousPeriodValue}} total. Growth: {{growthRatePct}}%. {{/if}} Full data: {{dataAsJson}} Summarize the signup trend and highlight any days with unusual volume. maxOutputTokens: 400 ``` # Activation Analysis (/docs/angular/concepts/insight_trackers/analysis_types/activation) Overview [#overview] Activation Analysis measures the "aha moment" rate — what percentage of users who completed a start event (e.g., signed up) also completed a key value action within a defined time window. It tells you how effective your onboarding is at guiding new users to first value. **When to use activation**: "What % of signups create a project within 24 hours?", "Are new users finding value quickly enough?", "What is our activation rate for trial users?" — any question about the rate at which new users reach a meaningful milestone. **When NOT to use activation**: If you want historical cohort return-rate curves, use [`retention`](./retention). If you want to identify currently inactive users, use [`churn`](./churn). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{newUsers}}` | Number of users who fired `startEvent` in the window | | `{{activated}}` | Number of users who also fired `ahaEvent` within `activationWindow` | | `{{activationRatePct}}` | Percentage of new users who activated | | `{{avgHoursToAha}}` | Average hours from `startEvent` to `ahaEvent` for activated users | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevActivationRatePct}}` | Activation rate in the previous period (when `hasComparison` is true) | | `{{activationDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-to-project.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-to-project displayName: Signup → First Project (24h Activation) description: What % of new signups create a project within 24 hours spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d analysis: type: activation entity: person_id startEvent: user_signed_up ahaEvent: project_created activationWindow: 24h compareWindow: previous_period llm: promptTemplate: | Analyze activation for {{windowPeriod}}. {{newUsers}} new users signed up. {{activated}} activated ({{activationRatePct}}%). Average time to aha moment: {{avgHoursToAha}} hours. {{#if hasComparison}} Previous period activation: {{prevActivationRatePct}}% ({{activationDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the biggest friction points preventing activation and suggest one targeted fix. maxOutputTokens: 400 ``` # Anomaly Detection (/docs/angular/concepts/insight_trackers/analysis_types/anomaly) Overview [#overview] Anomaly Detection automatically identifies unusual spikes or dips in a metric compared to a statistical baseline. This is alert-mode, not view-mode — the LLM is told **what deviated and by how much**, rather than being asked to interpret a time series. Use it for automatic monitoring of key metrics where you want to be notified when something unusual happens. **When to use anomaly**: "Alert me when error rates spike", "Did anything unusual happen with revenue this week?", "Detect and explain anomalies in daily active users." **When NOT to use anomaly**: If you want to *view* a time-series trend without automated detection, use [`trend`](./trend). If you want step-by-step drop-off analysis, use [`funnel`](./funnel). Configuration Reference [#configuration-reference] AnomalyMetricDef Properties [#anomalymetricdef-properties] AnomalyBaseline — type values [#anomalybaseline--type-values] | Value | Meaning | | -------------------------- | ----------------------------------------------------- | | `"rolling_average"` | Average of the metric over the last `windowDays` days | | `"same_period_last_week"` | Same time period from the previous week | | `"same_period_last_month"` | Same time period from the previous month | Available Template Variables [#available-template-variables] | Variable | Description | | -------------------- | ------------------------------------------------------------------------- | | `{{metricCount}}` | Number of metrics being monitored | | `{{totalAnomalies}}` | Total number of anomalous time buckets detected across all metrics | | `{{anomalySummary}}` | Per-metric anomaly details (metric label, deviation magnitude, direction) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/error-rate-anomaly.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: error-rate-anomaly displayName: Error Rate Anomaly Detection description: Alert when error event rates spike above statistical normal spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d granularity: hour analysis: type: anomaly metrics: - event: error_occurred aggregation: count groupBy: hour label: Error Rate - event: api_call_failed aggregation: count groupBy: hour label: API Failure Rate baseline: type: rolling_average windowDays: 14 threshold: stdDeviations: 2.5 minAbsoluteChange: 10 includeTimeSeries: false llm: promptTemplate: | Error monitoring report for {{windowPeriod}}. {{metricCount}} metrics monitored. {{totalAnomalies}} anomalous periods detected. Anomaly summary: {{anomalySummary}} Full data: {{dataAsJson}} Describe the most significant anomaly, its likely cause, and recommended response. maxOutputTokens: 500 ``` # Churn Risk Analysis (/docs/angular/concepts/insight_trackers/analysis_types/churn) Overview [#overview] Churn Risk Analysis finds users who were active during a lookback period but have not performed any qualifying activity within the inactivity threshold. These users are flagged as "at churn risk". The analysis gives you an actionable count today — not a historical trend. **When to use churn**: "Which users haven't logged in for 2 weeks?", "How many active users are at churn risk right now?", "Who do I need to reach out to before they leave?" — any question about currently at-risk users. **When NOT to use churn**: If you want historical retention trend curves over cohorts, use [`retention`](./retention). If you want a time-series activity count, use [`trend`](./trend). Configuration Reference [#configuration-reference] activeEvent values [#activeevent-values] | Value | Meaning | | --------------------------------- | ---------------------------------------------- | | `"*"` | Any event fired by the user counts as activity | | `"session_started"` | Only this specific event counts as activity | | `["session_started", "api_call"]` | Any event in this list counts as activity | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ------------------------------------------------------------------- | | `{{activeBase}}` | Total number of users who were active during the lookback period | | `{{atRiskCount}}` | Number of users currently at churn risk | | `{{atRiskRatePct}}` | Percentage of the active base that is at churn risk | | `{{churnSummary}}` | Segment breakdown of at-risk users (when `segments` are configured) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/churn-risk-14d.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: churn-risk-14d displayName: Churn Risk (14-day Inactivity) description: Users who were active in the last 90 days but silent for 14+ days spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d analysis: type: churn entity: person_id activeEvent: session_started inactivityThreshold: 14d lookbackPeriod: 90d segments: - property: plan metrics: - atRiskCount - atRiskRate - segmentBreakdown llm: promptTemplate: | Churn risk analysis for {{windowPeriod}}. Active user base: {{activeBase}}. At-risk users: {{atRiskCount}} ({{atRiskRatePct}}%). Segment breakdown: {{churnSummary}} Full data: {{dataAsJson}} Summarize the churn risk situation and recommend one re-engagement action. maxOutputTokens: 400 ``` # Cohort Analysis (/docs/angular/concepts/insight_trackers/analysis_types/cohort) Overview [#overview] Cohort Analysis groups users into cohorts — either by **when they first did something** (time-based) or by a **static property value** (e.g. plan tier) — and then compares a metric across those cohorts. Use it to answer "do users who joined in January behave differently to February signups?" or "how does purchase frequency differ across plan tiers?" **When to use cohort**: "Do users who signed up in January spend more than February signups?", "Compare engagement by plan tier", "Show LTV curves by acquisition month." **When NOT to use cohort**: If you want period-by-period return rates for a single cohort, use [`retention`](./retention). If you want a plain time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] CohortByFirstEvent Properties [#cohortbyfirstevent-properties] Groups users by the calendar period of their first occurrence of a specific event. CohortByProperty Properties [#cohortbyproperty-properties] Groups users by a static event property value (e.g. their plan at signup). CohortAggregation values [#cohortaggregation-values] | Value | Meaning | | --------------- | ------------------------------------------------------------ | | `"count"` | Total event occurrences in the cohort | | `"uniqueUsers"` | Unique users in the cohort who fired the metric event | | `"avg"` | Average value of a numeric property (requires `sumProperty`) | | `"sum"` | Sum of a numeric property (requires `sumProperty`) | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ---------------------------------------------------------- | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{avgCohortSize}}` | Average number of users per cohort | | `{{cohortSummary}}` | Per-cohort metric table (cohort label, size, metric value) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/weekly-cohort-purchases.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: weekly-cohort-purchases displayName: Weekly Signup Cohort → Purchase Comparison description: Compare purchase rates across weekly signup cohorts spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: cohort entity: person_id cohortDefinition: firstEvent: user_signed_up period: week metric: event: purchase_completed aggregation: uniqueUsers maxCohorts: 12 llm: promptTemplate: | Weekly cohort analysis for {{windowPeriod}}. {{cohortCount}} cohorts included. Average cohort size: {{avgCohortSize}} users. Cohort comparison: {{cohortSummary}} Full data: {{dataAsJson}} Identify which signup cohorts have the highest purchase rates and what might explain the difference. maxOutputTokens: 400 ``` # Conversion Rate (/docs/angular/concepts/insight_trackers/analysis_types/conversion) Overview [#overview] Conversion Rate computes a simple two-event rate: what percentage of users who performed event A also performed event B within the analysis window. This is a single ratio — there are no intermediate steps and no drop-off ordering. Use it for binary conversion questions. **When to use conversion**: "What is our trial-to-paid conversion rate?", "What % of visitors sign up?", "What is the lead-to-close rate in the last 30 days?" **When NOT to use conversion**: If you need 3 or more ordered steps with intermediate drop-off analysis, use [`funnel`](./funnel). If you want a time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{denominatorCount}}` | Number of users who fired `denominatorEvent` in the window | | `{{numeratorCount}}` | Number of those users who also fired `numeratorEvent` | | `{{conversionRatePct}}` | Conversion rate as a percentage | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevConversionRatePct}}` | Conversion rate in the previous period (when `hasComparison` is true) | | `{{conversionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/trial-to-paid.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: trial-to-paid displayName: Trial → Paid Conversion Rate description: Percentage of trial starts that convert to a paid subscription within 30 days spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: conversion entity: person_id denominatorEvent: trial_started numeratorEvent: subscription_started conversionWindow: 30d breakdowns: - property: plan maxCardinality: 5 compareWindow: previous_period llm: promptTemplate: | Trial-to-paid conversion for {{windowPeriod}}. {{denominatorCount}} trials started. {{numeratorCount}} converted ({{conversionRatePct}}%). {{#if hasComparison}} Previous period: {{prevConversionRatePct}}% ({{conversionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the primary driver of the conversion rate and recommend one improvement. maxOutputTokens: 400 ``` # Custom Analysis (/docs/angular/concepts/insight_trackers/analysis_types/custom) Custom analysis is not available in the AI-assisted tracker builder. Create custom trackers using the YAML editor. Overview [#overview] The `custom` analysis type passes a filtered list of raw events directly to the LLM for freeform analysis. Unlike structured types, it does not run pre-computed queries or inject metric variables — only the matching events and universal base variables are available. Use `custom` when none of the structured types fit your use case. Configuration Reference [#configuration-reference] RawEventsConfig Properties [#raweventsconfig-properties] Available Template Variables [#available-template-variables] `custom` analysis only has access to the universal base variables — no pre-computed metrics: | Variable | Description | | ------------------ | ---------------------------------------------------- | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Raw event list serialised as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/user-engagement.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: user-engagement displayName: User Engagement description: Tracks engagement patterns via raw event inspection spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: custom rawEvents: events: - signup_completed - habit_created - session_started minEvents: 1 maxEvents: 50 llm: promptTemplate: | Analyze user engagement for {{windowPeriod}}. Event data: {{dataAsJson}} Generate a one-sentence insight summarizing engagement patterns. maxOutputTokens: 200 ``` # Feature Adoption (/docs/angular/concepts/insight_trackers/analysis_types/feature_adoption) Overview [#overview] Feature Adoption measures what percentage of your **active users** have tried a specific feature at least once during the analysis window. The adoption rate is `unique feature users ÷ total active users in the period`. This is distinct from a raw usage count — it tells you about feature discovery and uptake relative to your active user base. **When to use featureAdoption**: "How many active users have tried the new AI assistant?", "What is the adoption rate of the export feature?", "Is v2 dashboard adoption growing month over month?" **When NOT to use featureAdoption**: If you want a raw time-series count of feature usage, use [`trend`](./trend). If you want a simple rate not tied to the active user base, use [`conversion`](./conversion). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | -------------------------------------------------------------------------- | | `{{activeBaseCount}}` | Total active users in the analysis window | | `{{uniqueAdopters}}` | Users who fired at least one feature event | | `{{adoptionRatePct}}` | Percentage of active users who adopted the feature | | `{{avgUsesPerAdopter}}` | Average number of feature interactions per adopter | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevAdoptionRatePct}}` | Adoption rate in the previous period (when `hasComparison` is true) | | `{{adoptionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/ai-assistant-adoption.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: ai-assistant-adoption displayName: AI Assistant Feature Adoption description: What fraction of active users have tried the AI assistant spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: featureAdoption entity: person_id featureEvents: - event: ai_assistant_opened label: Opened AI Assistant - event: ai_suggestion_accepted label: Accepted AI Suggestion activeUserBaseline: event: session_started period: 30d breakdowns: - property: plan maxCardinality: 5 metrics: - adoptionRate - avgUsesPerAdopter - weekOverWeekDelta compareWindow: previous_period llm: promptTemplate: | AI assistant adoption analysis for {{windowPeriod}}. Active user base: {{activeBaseCount}}. Adopters: {{uniqueAdopters}} ({{adoptionRatePct}}%). Average uses per adopter: {{avgUsesPerAdopter}}. {{#if hasComparison}} Previous period: {{prevAdoptionRatePct}}% ({{adoptionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Describe whether adoption is healthy and suggest one action to increase it. maxOutputTokens: 400 ``` # Funnel Analysis (/docs/angular/concepts/insight_trackers/analysis_types/funnel) Overview [#overview] Funnel Analysis tracks how users progress through an **ordered series of steps** and shows exactly where they drop off. Use it whenever the key question is "how many users made it from step A to step B (to step C …)?" and you need to see intermediate drop-off at each stage. **When to use funnel**: Checkout flows, onboarding wizards, trial-to-paid flows, signup sequences, feature setup journeys — any multi-step process where order matters and drop-off location is the insight you care about. **When NOT to use funnel**: If you only need a single A → B rate without step ordering, use [`conversion`](./conversion). If you want a time-series count of step completions, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | -------------------------- | ------------------------------------------------------------------ | | `{{totalEntrants}}` | Number of users who completed the first funnel step | | `{{overallConversionPct}}` | Percentage of entrants who completed the final step | | `{{stepsSummary}}` | Step-by-step conversion table (label, count, CVR%) | | `{{worstStep}}` | Label of the step with the highest absolute user loss | | `{{worstStepCvr}}` | Conversion rate (%) at the worst step | | `{{worstStepLoss}}` | Number of users lost at the worst step | | `{{hasBreakdown}}` | `true` if breakdown data is present | | `{{breakdownSummary}}` | Breakdown results table (only present when `hasBreakdown` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 actionable recommendations to improve conversion at the weakest step. maxOutputTokens: 500 ``` # Analysis Types (/docs/angular/concepts/insight_trackers/analysis_types) Journium trackers use a structured `analysis` block that selects one of nine structured analysis algorithms, plus Custom analysis. Each type determines: * **What queries are compiled** against your event data * **Which template variables** are injected into your `llm.promptTemplate` * **What computed metrics** are surfaced in the insight Choosing the Right Type [#choosing-the-right-type] }> Track ordered step completion and identify where users drop off. }> Cohort return-rate curves over time — D1, D7, D30, and beyond. }> Measure what percentage of new users reach the first value moment. }> Identify users who were active but have since gone silent. }> What fraction of active users have tried a specific feature. }> Automated spike and dip detection vs. a statistical baseline. }> Simple numerator / denominator rate — percentage of group A that does B. }> Compare a metric across cohorts defined by join date or a property value. }> Count events or unique users per time period — daily, weekly, monthly. }> Pass raw matching events to the LLM — not available in the NL Builder. Quick Selection Guide [#quick-selection-guide] | If you want to… | Use type | | ---------------------------------------------------------- | ----------------- | | See where users drop off across an ordered multi-step flow | `funnel` | | Track what fraction of cohorts return at D1 / D7 / D30 | `retention` | | Measure the aha-moment rate for new users | `activation` | | Find users who went quiet and are at risk of churning | `churn` | | Know what fraction of active users have adopted a feature | `featureAdoption` | | Get alerted when a metric spikes or dips anomalously | `anomaly` | | Compute a simple event-A-to-event-B conversion rate | `conversion` | | Compare engagement or revenue across cohort groups | `cohort` | | Plot event counts, DAU, or sums over time | `trend` | | Analyze matching events without pre-computed metrics | `custom` | Universal Template Variables [#universal-template-variables] All analysis types inject these variables into `llm.promptTemplate`: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured analysis result serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Each analysis type also provides its own type-specific variables. See the individual type pages for details. # Retention Analysis (/docs/angular/concepts/insight_trackers/analysis_types/retention) Overview [#overview] Retention Analysis measures what fraction of users who first performed an action (e.g., signed up) came back and performed a retention event at specified intervals (Day 1, Day 7, Day 30, etc.). It groups users into cohorts by the period they first acted and plots return rates for each cohort. **When to use retention**: "Are users coming back?", "How sticky is the product?", "Show me D7 and D30 retention after signup" — any question about cohort-based return rates over time. **When NOT to use retention**: If you want to identify who is *currently* inactive or at risk today, use [`churn`](./churn). If you want to measure the first-value-moment rate for new users, use [`activation`](./activation). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ---------------------- | ------------------------------------------------------------------------------------------ | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{retentionSummary}}` | Cohort × interval retention matrix (cohort label, size, and return rates at each interval) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-retention.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-retention displayName: Signup Retention (D1 / D7 / D30) description: Weekly cohort retention after signup spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: retention entity: person_id cohortEvent: user_signed_up retentionEvent: session_started cohortPeriod: week intervals: [1, 7, 14, 30] minCohortSize: 20 maxCohorts: 12 llm: promptTemplate: | Analyze signup retention for {{windowPeriod}}. {{cohortCount}} weekly cohorts included. Retention matrix: {{retentionSummary}} Full data: {{dataAsJson}} Identify the cohorts with the best and worst D7 retention, and suggest one actionable improvement for early-session engagement. maxOutputTokens: 400 ``` # Trend / Growth (/docs/angular/concepts/insight_trackers/analysis_types/trend) Overview [#overview] Trend Analysis computes a time-series of an aggregated metric bucketed by `hour`, `day`, `week`, or `month`. It covers all growth and usage-frequency questions. "How many times does X happen per period?" is always a trend question. **When to use trend**: "How many users are signing up every month?", "Show me daily active users over the last 90 days", "What is the weekly trend in purchases over the past quarter?" **When NOT to use trend**: If you want automated spike/dip alerts, use [`anomaly`](./anomaly). If you want cohort return curves, use [`retention`](./retention). If you want to compare groups, use [`cohort`](./cohort). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | ------------------------------------------------------------------------- | | `{{metricName}}` | Human-readable name for the metric (derived from `event` + `aggregation`) | | `{{periodCount}}` | Number of time buckets in the result | | `{{currentPeriodValue}}` | Value in the most recent complete time bucket | | `{{peakPeriod}}` | Label of the time bucket with the highest value | | `{{peakValue}}` | The value at the peak period | | `{{trendDirection}}` | Overall trend direction: `"up"`, `"down"`, or `"flat"` | | `{{trendSummary}}` | Human-readable summary of the trend (e.g. "grew 12% week-over-week") | | `{{hasComparison}}` | `true` if `compareWindow` data is available | | `{{previousPeriodValue}}` | Value in the equivalent previous period (when `hasComparison` is true) | | `{{growthRatePct}}` | Percentage change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/daily-signups-trend.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: daily-signups-trend displayName: Daily Signups Trend (WoW) description: Daily signup count with week-over-week comparison spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d granularity: day analysis: type: trend entity: person_id event: user_signed_up aggregation: uniqueUsers groupBy: day compareWindow: previous_period llm: promptTemplate: | Daily signup trend for {{windowPeriod}}. Metric: {{metricName}} — {{periodCount}} days. Most recent day: {{currentPeriodValue}} signups. Peak day: {{peakPeriod}} ({{peakValue}} signups). Overall trend: {{trendDirection}}. {{trendSummary}} {{#if hasComparison}} Previous period: {{previousPeriodValue}} total. Growth: {{growthRatePct}}%. {{/if}} Full data: {{dataAsJson}} Summarize the signup trend and highlight any days with unusual volume. maxOutputTokens: 400 ``` # Activation Analysis (/docs/js/concepts/insight_trackers/analysis_types/activation) Overview [#overview] Activation Analysis measures the "aha moment" rate — what percentage of users who completed a start event (e.g., signed up) also completed a key value action within a defined time window. It tells you how effective your onboarding is at guiding new users to first value. **When to use activation**: "What % of signups create a project within 24 hours?", "Are new users finding value quickly enough?", "What is our activation rate for trial users?" — any question about the rate at which new users reach a meaningful milestone. **When NOT to use activation**: If you want historical cohort return-rate curves, use [`retention`](./retention). If you want to identify currently inactive users, use [`churn`](./churn). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{newUsers}}` | Number of users who fired `startEvent` in the window | | `{{activated}}` | Number of users who also fired `ahaEvent` within `activationWindow` | | `{{activationRatePct}}` | Percentage of new users who activated | | `{{avgHoursToAha}}` | Average hours from `startEvent` to `ahaEvent` for activated users | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevActivationRatePct}}` | Activation rate in the previous period (when `hasComparison` is true) | | `{{activationDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-to-project.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-to-project displayName: Signup → First Project (24h Activation) description: What % of new signups create a project within 24 hours spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d analysis: type: activation entity: person_id startEvent: user_signed_up ahaEvent: project_created activationWindow: 24h compareWindow: previous_period llm: promptTemplate: | Analyze activation for {{windowPeriod}}. {{newUsers}} new users signed up. {{activated}} activated ({{activationRatePct}}%). Average time to aha moment: {{avgHoursToAha}} hours. {{#if hasComparison}} Previous period activation: {{prevActivationRatePct}}% ({{activationDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the biggest friction points preventing activation and suggest one targeted fix. maxOutputTokens: 400 ``` # Anomaly Detection (/docs/js/concepts/insight_trackers/analysis_types/anomaly) Overview [#overview] Anomaly Detection automatically identifies unusual spikes or dips in a metric compared to a statistical baseline. This is alert-mode, not view-mode — the LLM is told **what deviated and by how much**, rather than being asked to interpret a time series. Use it for automatic monitoring of key metrics where you want to be notified when something unusual happens. **When to use anomaly**: "Alert me when error rates spike", "Did anything unusual happen with revenue this week?", "Detect and explain anomalies in daily active users." **When NOT to use anomaly**: If you want to *view* a time-series trend without automated detection, use [`trend`](./trend). If you want step-by-step drop-off analysis, use [`funnel`](./funnel). Configuration Reference [#configuration-reference] AnomalyMetricDef Properties [#anomalymetricdef-properties] AnomalyBaseline — type values [#anomalybaseline--type-values] | Value | Meaning | | -------------------------- | ----------------------------------------------------- | | `"rolling_average"` | Average of the metric over the last `windowDays` days | | `"same_period_last_week"` | Same time period from the previous week | | `"same_period_last_month"` | Same time period from the previous month | Available Template Variables [#available-template-variables] | Variable | Description | | -------------------- | ------------------------------------------------------------------------- | | `{{metricCount}}` | Number of metrics being monitored | | `{{totalAnomalies}}` | Total number of anomalous time buckets detected across all metrics | | `{{anomalySummary}}` | Per-metric anomaly details (metric label, deviation magnitude, direction) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/error-rate-anomaly.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: error-rate-anomaly displayName: Error Rate Anomaly Detection description: Alert when error event rates spike above statistical normal spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d granularity: hour analysis: type: anomaly metrics: - event: error_occurred aggregation: count groupBy: hour label: Error Rate - event: api_call_failed aggregation: count groupBy: hour label: API Failure Rate baseline: type: rolling_average windowDays: 14 threshold: stdDeviations: 2.5 minAbsoluteChange: 10 includeTimeSeries: false llm: promptTemplate: | Error monitoring report for {{windowPeriod}}. {{metricCount}} metrics monitored. {{totalAnomalies}} anomalous periods detected. Anomaly summary: {{anomalySummary}} Full data: {{dataAsJson}} Describe the most significant anomaly, its likely cause, and recommended response. maxOutputTokens: 500 ``` # Churn Risk Analysis (/docs/js/concepts/insight_trackers/analysis_types/churn) Overview [#overview] Churn Risk Analysis finds users who were active during a lookback period but have not performed any qualifying activity within the inactivity threshold. These users are flagged as "at churn risk". The analysis gives you an actionable count today — not a historical trend. **When to use churn**: "Which users haven't logged in for 2 weeks?", "How many active users are at churn risk right now?", "Who do I need to reach out to before they leave?" — any question about currently at-risk users. **When NOT to use churn**: If you want historical retention trend curves over cohorts, use [`retention`](./retention). If you want a time-series activity count, use [`trend`](./trend). Configuration Reference [#configuration-reference] activeEvent values [#activeevent-values] | Value | Meaning | | --------------------------------- | ---------------------------------------------- | | `"*"` | Any event fired by the user counts as activity | | `"session_started"` | Only this specific event counts as activity | | `["session_started", "api_call"]` | Any event in this list counts as activity | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ------------------------------------------------------------------- | | `{{activeBase}}` | Total number of users who were active during the lookback period | | `{{atRiskCount}}` | Number of users currently at churn risk | | `{{atRiskRatePct}}` | Percentage of the active base that is at churn risk | | `{{churnSummary}}` | Segment breakdown of at-risk users (when `segments` are configured) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/churn-risk-14d.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: churn-risk-14d displayName: Churn Risk (14-day Inactivity) description: Users who were active in the last 90 days but silent for 14+ days spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d analysis: type: churn entity: person_id activeEvent: session_started inactivityThreshold: 14d lookbackPeriod: 90d segments: - property: plan metrics: - atRiskCount - atRiskRate - segmentBreakdown llm: promptTemplate: | Churn risk analysis for {{windowPeriod}}. Active user base: {{activeBase}}. At-risk users: {{atRiskCount}} ({{atRiskRatePct}}%). Segment breakdown: {{churnSummary}} Full data: {{dataAsJson}} Summarize the churn risk situation and recommend one re-engagement action. maxOutputTokens: 400 ``` # Cohort Analysis (/docs/js/concepts/insight_trackers/analysis_types/cohort) Overview [#overview] Cohort Analysis groups users into cohorts — either by **when they first did something** (time-based) or by a **static property value** (e.g. plan tier) — and then compares a metric across those cohorts. Use it to answer "do users who joined in January behave differently to February signups?" or "how does purchase frequency differ across plan tiers?" **When to use cohort**: "Do users who signed up in January spend more than February signups?", "Compare engagement by plan tier", "Show LTV curves by acquisition month." **When NOT to use cohort**: If you want period-by-period return rates for a single cohort, use [`retention`](./retention). If you want a plain time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] CohortByFirstEvent Properties [#cohortbyfirstevent-properties] Groups users by the calendar period of their first occurrence of a specific event. CohortByProperty Properties [#cohortbyproperty-properties] Groups users by a static event property value (e.g. their plan at signup). CohortAggregation values [#cohortaggregation-values] | Value | Meaning | | --------------- | ------------------------------------------------------------ | | `"count"` | Total event occurrences in the cohort | | `"uniqueUsers"` | Unique users in the cohort who fired the metric event | | `"avg"` | Average value of a numeric property (requires `sumProperty`) | | `"sum"` | Sum of a numeric property (requires `sumProperty`) | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ---------------------------------------------------------- | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{avgCohortSize}}` | Average number of users per cohort | | `{{cohortSummary}}` | Per-cohort metric table (cohort label, size, metric value) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/weekly-cohort-purchases.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: weekly-cohort-purchases displayName: Weekly Signup Cohort → Purchase Comparison description: Compare purchase rates across weekly signup cohorts spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: cohort entity: person_id cohortDefinition: firstEvent: user_signed_up period: week metric: event: purchase_completed aggregation: uniqueUsers maxCohorts: 12 llm: promptTemplate: | Weekly cohort analysis for {{windowPeriod}}. {{cohortCount}} cohorts included. Average cohort size: {{avgCohortSize}} users. Cohort comparison: {{cohortSummary}} Full data: {{dataAsJson}} Identify which signup cohorts have the highest purchase rates and what might explain the difference. maxOutputTokens: 400 ``` # Conversion Rate (/docs/js/concepts/insight_trackers/analysis_types/conversion) Overview [#overview] Conversion Rate computes a simple two-event rate: what percentage of users who performed event A also performed event B within the analysis window. This is a single ratio — there are no intermediate steps and no drop-off ordering. Use it for binary conversion questions. **When to use conversion**: "What is our trial-to-paid conversion rate?", "What % of visitors sign up?", "What is the lead-to-close rate in the last 30 days?" **When NOT to use conversion**: If you need 3 or more ordered steps with intermediate drop-off analysis, use [`funnel`](./funnel). If you want a time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{denominatorCount}}` | Number of users who fired `denominatorEvent` in the window | | `{{numeratorCount}}` | Number of those users who also fired `numeratorEvent` | | `{{conversionRatePct}}` | Conversion rate as a percentage | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevConversionRatePct}}` | Conversion rate in the previous period (when `hasComparison` is true) | | `{{conversionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/trial-to-paid.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: trial-to-paid displayName: Trial → Paid Conversion Rate description: Percentage of trial starts that convert to a paid subscription within 30 days spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: conversion entity: person_id denominatorEvent: trial_started numeratorEvent: subscription_started conversionWindow: 30d breakdowns: - property: plan maxCardinality: 5 compareWindow: previous_period llm: promptTemplate: | Trial-to-paid conversion for {{windowPeriod}}. {{denominatorCount}} trials started. {{numeratorCount}} converted ({{conversionRatePct}}%). {{#if hasComparison}} Previous period: {{prevConversionRatePct}}% ({{conversionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the primary driver of the conversion rate and recommend one improvement. maxOutputTokens: 400 ``` # Custom Analysis (/docs/js/concepts/insight_trackers/analysis_types/custom) Custom analysis is not available in the AI-assisted tracker builder. Create custom trackers using the YAML editor. Overview [#overview] The `custom` analysis type passes a filtered list of raw events directly to the LLM for freeform analysis. Unlike structured types, it does not run pre-computed queries or inject metric variables — only the matching events and universal base variables are available. Use `custom` when none of the structured types fit your use case. Configuration Reference [#configuration-reference] RawEventsConfig Properties [#raweventsconfig-properties] Available Template Variables [#available-template-variables] `custom` analysis only has access to the universal base variables — no pre-computed metrics: | Variable | Description | | ------------------ | ---------------------------------------------------- | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Raw event list serialised as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/user-engagement.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: user-engagement displayName: User Engagement description: Tracks engagement patterns via raw event inspection spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: custom rawEvents: events: - signup_completed - habit_created - session_started minEvents: 1 maxEvents: 50 llm: promptTemplate: | Analyze user engagement for {{windowPeriod}}. Event data: {{dataAsJson}} Generate a one-sentence insight summarizing engagement patterns. maxOutputTokens: 200 ``` # Feature Adoption (/docs/js/concepts/insight_trackers/analysis_types/feature_adoption) Overview [#overview] Feature Adoption measures what percentage of your **active users** have tried a specific feature at least once during the analysis window. The adoption rate is `unique feature users ÷ total active users in the period`. This is distinct from a raw usage count — it tells you about feature discovery and uptake relative to your active user base. **When to use featureAdoption**: "How many active users have tried the new AI assistant?", "What is the adoption rate of the export feature?", "Is v2 dashboard adoption growing month over month?" **When NOT to use featureAdoption**: If you want a raw time-series count of feature usage, use [`trend`](./trend). If you want a simple rate not tied to the active user base, use [`conversion`](./conversion). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | -------------------------------------------------------------------------- | | `{{activeBaseCount}}` | Total active users in the analysis window | | `{{uniqueAdopters}}` | Users who fired at least one feature event | | `{{adoptionRatePct}}` | Percentage of active users who adopted the feature | | `{{avgUsesPerAdopter}}` | Average number of feature interactions per adopter | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevAdoptionRatePct}}` | Adoption rate in the previous period (when `hasComparison` is true) | | `{{adoptionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/ai-assistant-adoption.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: ai-assistant-adoption displayName: AI Assistant Feature Adoption description: What fraction of active users have tried the AI assistant spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: featureAdoption entity: person_id featureEvents: - event: ai_assistant_opened label: Opened AI Assistant - event: ai_suggestion_accepted label: Accepted AI Suggestion activeUserBaseline: event: session_started period: 30d breakdowns: - property: plan maxCardinality: 5 metrics: - adoptionRate - avgUsesPerAdopter - weekOverWeekDelta compareWindow: previous_period llm: promptTemplate: | AI assistant adoption analysis for {{windowPeriod}}. Active user base: {{activeBaseCount}}. Adopters: {{uniqueAdopters}} ({{adoptionRatePct}}%). Average uses per adopter: {{avgUsesPerAdopter}}. {{#if hasComparison}} Previous period: {{prevAdoptionRatePct}}% ({{adoptionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Describe whether adoption is healthy and suggest one action to increase it. maxOutputTokens: 400 ``` # Funnel Analysis (/docs/js/concepts/insight_trackers/analysis_types/funnel) Overview [#overview] Funnel Analysis tracks how users progress through an **ordered series of steps** and shows exactly where they drop off. Use it whenever the key question is "how many users made it from step A to step B (to step C …)?" and you need to see intermediate drop-off at each stage. **When to use funnel**: Checkout flows, onboarding wizards, trial-to-paid flows, signup sequences, feature setup journeys — any multi-step process where order matters and drop-off location is the insight you care about. **When NOT to use funnel**: If you only need a single A → B rate without step ordering, use [`conversion`](./conversion). If you want a time-series count of step completions, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | -------------------------- | ------------------------------------------------------------------ | | `{{totalEntrants}}` | Number of users who completed the first funnel step | | `{{overallConversionPct}}` | Percentage of entrants who completed the final step | | `{{stepsSummary}}` | Step-by-step conversion table (label, count, CVR%) | | `{{worstStep}}` | Label of the step with the highest absolute user loss | | `{{worstStepCvr}}` | Conversion rate (%) at the worst step | | `{{worstStepLoss}}` | Number of users lost at the worst step | | `{{hasBreakdown}}` | `true` if breakdown data is present | | `{{breakdownSummary}}` | Breakdown results table (only present when `hasBreakdown` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 actionable recommendations to improve conversion at the weakest step. maxOutputTokens: 500 ``` # Analysis Types (/docs/js/concepts/insight_trackers/analysis_types) Journium trackers use a structured `analysis` block that selects one of nine structured analysis algorithms, plus Custom analysis. Each type determines: * **What queries are compiled** against your event data * **Which template variables** are injected into your `llm.promptTemplate` * **What computed metrics** are surfaced in the insight Choosing the Right Type [#choosing-the-right-type] }> Track ordered step completion and identify where users drop off. }> Cohort return-rate curves over time — D1, D7, D30, and beyond. }> Measure what percentage of new users reach the first value moment. }> Identify users who were active but have since gone silent. }> What fraction of active users have tried a specific feature. }> Automated spike and dip detection vs. a statistical baseline. }> Simple numerator / denominator rate — percentage of group A that does B. }> Compare a metric across cohorts defined by join date or a property value. }> Count events or unique users per time period — daily, weekly, monthly. }> Pass raw matching events to the LLM — not available in the NL Builder. Quick Selection Guide [#quick-selection-guide] | If you want to… | Use type | | ---------------------------------------------------------- | ----------------- | | See where users drop off across an ordered multi-step flow | `funnel` | | Track what fraction of cohorts return at D1 / D7 / D30 | `retention` | | Measure the aha-moment rate for new users | `activation` | | Find users who went quiet and are at risk of churning | `churn` | | Know what fraction of active users have adopted a feature | `featureAdoption` | | Get alerted when a metric spikes or dips anomalously | `anomaly` | | Compute a simple event-A-to-event-B conversion rate | `conversion` | | Compare engagement or revenue across cohort groups | `cohort` | | Plot event counts, DAU, or sums over time | `trend` | | Analyze matching events without pre-computed metrics | `custom` | Universal Template Variables [#universal-template-variables] All analysis types inject these variables into `llm.promptTemplate`: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured analysis result serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Each analysis type also provides its own type-specific variables. See the individual type pages for details. # Retention Analysis (/docs/js/concepts/insight_trackers/analysis_types/retention) Overview [#overview] Retention Analysis measures what fraction of users who first performed an action (e.g., signed up) came back and performed a retention event at specified intervals (Day 1, Day 7, Day 30, etc.). It groups users into cohorts by the period they first acted and plots return rates for each cohort. **When to use retention**: "Are users coming back?", "How sticky is the product?", "Show me D7 and D30 retention after signup" — any question about cohort-based return rates over time. **When NOT to use retention**: If you want to identify who is *currently* inactive or at risk today, use [`churn`](./churn). If you want to measure the first-value-moment rate for new users, use [`activation`](./activation). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ---------------------- | ------------------------------------------------------------------------------------------ | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{retentionSummary}}` | Cohort × interval retention matrix (cohort label, size, and return rates at each interval) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-retention.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-retention displayName: Signup Retention (D1 / D7 / D30) description: Weekly cohort retention after signup spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: retention entity: person_id cohortEvent: user_signed_up retentionEvent: session_started cohortPeriod: week intervals: [1, 7, 14, 30] minCohortSize: 20 maxCohorts: 12 llm: promptTemplate: | Analyze signup retention for {{windowPeriod}}. {{cohortCount}} weekly cohorts included. Retention matrix: {{retentionSummary}} Full data: {{dataAsJson}} Identify the cohorts with the best and worst D7 retention, and suggest one actionable improvement for early-session engagement. maxOutputTokens: 400 ``` # Trend / Growth (/docs/js/concepts/insight_trackers/analysis_types/trend) Overview [#overview] Trend Analysis computes a time-series of an aggregated metric bucketed by `hour`, `day`, `week`, or `month`. It covers all growth and usage-frequency questions. "How many times does X happen per period?" is always a trend question. **When to use trend**: "How many users are signing up every month?", "Show me daily active users over the last 90 days", "What is the weekly trend in purchases over the past quarter?" **When NOT to use trend**: If you want automated spike/dip alerts, use [`anomaly`](./anomaly). If you want cohort return curves, use [`retention`](./retention). If you want to compare groups, use [`cohort`](./cohort). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | ------------------------------------------------------------------------- | | `{{metricName}}` | Human-readable name for the metric (derived from `event` + `aggregation`) | | `{{periodCount}}` | Number of time buckets in the result | | `{{currentPeriodValue}}` | Value in the most recent complete time bucket | | `{{peakPeriod}}` | Label of the time bucket with the highest value | | `{{peakValue}}` | The value at the peak period | | `{{trendDirection}}` | Overall trend direction: `"up"`, `"down"`, or `"flat"` | | `{{trendSummary}}` | Human-readable summary of the trend (e.g. "grew 12% week-over-week") | | `{{hasComparison}}` | `true` if `compareWindow` data is available | | `{{previousPeriodValue}}` | Value in the equivalent previous period (when `hasComparison` is true) | | `{{growthRatePct}}` | Percentage change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/daily-signups-trend.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: daily-signups-trend displayName: Daily Signups Trend (WoW) description: Daily signup count with week-over-week comparison spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d granularity: day analysis: type: trend entity: person_id event: user_signed_up aggregation: uniqueUsers groupBy: day compareWindow: previous_period llm: promptTemplate: | Daily signup trend for {{windowPeriod}}. Metric: {{metricName}} — {{periodCount}} days. Most recent day: {{currentPeriodValue}} signups. Peak day: {{peakPeriod}} ({{peakValue}} signups). Overall trend: {{trendDirection}}. {{trendSummary}} {{#if hasComparison}} Previous period: {{previousPeriodValue}} total. Growth: {{growthRatePct}}%. {{/if}} Full data: {{dataAsJson}} Summarize the signup trend and highlight any days with unusual volume. maxOutputTokens: 400 ``` # Activation Analysis (/docs/react/concepts/insight_trackers/analysis_types/activation) Overview [#overview] Activation Analysis measures the "aha moment" rate — what percentage of users who completed a start event (e.g., signed up) also completed a key value action within a defined time window. It tells you how effective your onboarding is at guiding new users to first value. **When to use activation**: "What % of signups create a project within 24 hours?", "Are new users finding value quickly enough?", "What is our activation rate for trial users?" — any question about the rate at which new users reach a meaningful milestone. **When NOT to use activation**: If you want historical cohort return-rate curves, use [`retention`](./retention). If you want to identify currently inactive users, use [`churn`](./churn). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{newUsers}}` | Number of users who fired `startEvent` in the window | | `{{activated}}` | Number of users who also fired `ahaEvent` within `activationWindow` | | `{{activationRatePct}}` | Percentage of new users who activated | | `{{avgHoursToAha}}` | Average hours from `startEvent` to `ahaEvent` for activated users | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevActivationRatePct}}` | Activation rate in the previous period (when `hasComparison` is true) | | `{{activationDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-to-project.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-to-project displayName: Signup → First Project (24h Activation) description: What % of new signups create a project within 24 hours spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d analysis: type: activation entity: person_id startEvent: user_signed_up ahaEvent: project_created activationWindow: 24h compareWindow: previous_period llm: promptTemplate: | Analyze activation for {{windowPeriod}}. {{newUsers}} new users signed up. {{activated}} activated ({{activationRatePct}}%). Average time to aha moment: {{avgHoursToAha}} hours. {{#if hasComparison}} Previous period activation: {{prevActivationRatePct}}% ({{activationDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the biggest friction points preventing activation and suggest one targeted fix. maxOutputTokens: 400 ``` # Anomaly Detection (/docs/react/concepts/insight_trackers/analysis_types/anomaly) Overview [#overview] Anomaly Detection automatically identifies unusual spikes or dips in a metric compared to a statistical baseline. This is alert-mode, not view-mode — the LLM is told **what deviated and by how much**, rather than being asked to interpret a time series. Use it for automatic monitoring of key metrics where you want to be notified when something unusual happens. **When to use anomaly**: "Alert me when error rates spike", "Did anything unusual happen with revenue this week?", "Detect and explain anomalies in daily active users." **When NOT to use anomaly**: If you want to *view* a time-series trend without automated detection, use [`trend`](./trend). If you want step-by-step drop-off analysis, use [`funnel`](./funnel). Configuration Reference [#configuration-reference] AnomalyMetricDef Properties [#anomalymetricdef-properties] AnomalyBaseline — type values [#anomalybaseline--type-values] | Value | Meaning | | -------------------------- | ----------------------------------------------------- | | `"rolling_average"` | Average of the metric over the last `windowDays` days | | `"same_period_last_week"` | Same time period from the previous week | | `"same_period_last_month"` | Same time period from the previous month | Available Template Variables [#available-template-variables] | Variable | Description | | -------------------- | ------------------------------------------------------------------------- | | `{{metricCount}}` | Number of metrics being monitored | | `{{totalAnomalies}}` | Total number of anomalous time buckets detected across all metrics | | `{{anomalySummary}}` | Per-metric anomaly details (metric label, deviation magnitude, direction) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 14 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/error-rate-anomaly.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: error-rate-anomaly displayName: Error Rate Anomaly Detection description: Alert when error event rates spike above statistical normal spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_14d granularity: hour analysis: type: anomaly metrics: - event: error_occurred aggregation: count groupBy: hour label: Error Rate - event: api_call_failed aggregation: count groupBy: hour label: API Failure Rate baseline: type: rolling_average windowDays: 14 threshold: stdDeviations: 2.5 minAbsoluteChange: 10 includeTimeSeries: false llm: promptTemplate: | Error monitoring report for {{windowPeriod}}. {{metricCount}} metrics monitored. {{totalAnomalies}} anomalous periods detected. Anomaly summary: {{anomalySummary}} Full data: {{dataAsJson}} Describe the most significant anomaly, its likely cause, and recommended response. maxOutputTokens: 500 ``` # Churn Risk Analysis (/docs/react/concepts/insight_trackers/analysis_types/churn) Overview [#overview] Churn Risk Analysis finds users who were active during a lookback period but have not performed any qualifying activity within the inactivity threshold. These users are flagged as "at churn risk". The analysis gives you an actionable count today — not a historical trend. **When to use churn**: "Which users haven't logged in for 2 weeks?", "How many active users are at churn risk right now?", "Who do I need to reach out to before they leave?" — any question about currently at-risk users. **When NOT to use churn**: If you want historical retention trend curves over cohorts, use [`retention`](./retention). If you want a time-series activity count, use [`trend`](./trend). Configuration Reference [#configuration-reference] activeEvent values [#activeevent-values] | Value | Meaning | | --------------------------------- | ---------------------------------------------- | | `"*"` | Any event fired by the user counts as activity | | `"session_started"` | Only this specific event counts as activity | | `["session_started", "api_call"]` | Any event in this list counts as activity | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ------------------------------------------------------------------- | | `{{activeBase}}` | Total number of users who were active during the lookback period | | `{{atRiskCount}}` | Number of users currently at churn risk | | `{{atRiskRatePct}}` | Percentage of the active base that is at churn risk | | `{{churnSummary}}` | Segment breakdown of at-risk users (when `segments` are configured) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/churn-risk-14d.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: churn-risk-14d displayName: Churn Risk (14-day Inactivity) description: Users who were active in the last 90 days but silent for 14+ days spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d analysis: type: churn entity: person_id activeEvent: session_started inactivityThreshold: 14d lookbackPeriod: 90d segments: - property: plan metrics: - atRiskCount - atRiskRate - segmentBreakdown llm: promptTemplate: | Churn risk analysis for {{windowPeriod}}. Active user base: {{activeBase}}. At-risk users: {{atRiskCount}} ({{atRiskRatePct}}%). Segment breakdown: {{churnSummary}} Full data: {{dataAsJson}} Summarize the churn risk situation and recommend one re-engagement action. maxOutputTokens: 400 ``` # Cohort Analysis (/docs/react/concepts/insight_trackers/analysis_types/cohort) Overview [#overview] Cohort Analysis groups users into cohorts — either by **when they first did something** (time-based) or by a **static property value** (e.g. plan tier) — and then compares a metric across those cohorts. Use it to answer "do users who joined in January behave differently to February signups?" or "how does purchase frequency differ across plan tiers?" **When to use cohort**: "Do users who signed up in January spend more than February signups?", "Compare engagement by plan tier", "Show LTV curves by acquisition month." **When NOT to use cohort**: If you want period-by-period return rates for a single cohort, use [`retention`](./retention). If you want a plain time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] CohortByFirstEvent Properties [#cohortbyfirstevent-properties] Groups users by the calendar period of their first occurrence of a specific event. CohortByProperty Properties [#cohortbyproperty-properties] Groups users by a static event property value (e.g. their plan at signup). CohortAggregation values [#cohortaggregation-values] | Value | Meaning | | --------------- | ------------------------------------------------------------ | | `"count"` | Total event occurrences in the cohort | | `"uniqueUsers"` | Unique users in the cohort who fired the metric event | | `"avg"` | Average value of a numeric property (requires `sumProperty`) | | `"sum"` | Sum of a numeric property (requires `sumProperty`) | Available Template Variables [#available-template-variables] | Variable | Description | | ------------------- | ---------------------------------------------------------- | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{avgCohortSize}}` | Average number of users per cohort | | `{{cohortSummary}}` | Per-cohort metric table (cohort label, size, metric value) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/weekly-cohort-purchases.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: weekly-cohort-purchases displayName: Weekly Signup Cohort → Purchase Comparison description: Compare purchase rates across weekly signup cohorts spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: cohort entity: person_id cohortDefinition: firstEvent: user_signed_up period: week metric: event: purchase_completed aggregation: uniqueUsers maxCohorts: 12 llm: promptTemplate: | Weekly cohort analysis for {{windowPeriod}}. {{cohortCount}} cohorts included. Average cohort size: {{avgCohortSize}} users. Cohort comparison: {{cohortSummary}} Full data: {{dataAsJson}} Identify which signup cohorts have the highest purchase rates and what might explain the difference. maxOutputTokens: 400 ``` # Conversion Rate (/docs/react/concepts/insight_trackers/analysis_types/conversion) Overview [#overview] Conversion Rate computes a simple two-event rate: what percentage of users who performed event A also performed event B within the analysis window. This is a single ratio — there are no intermediate steps and no drop-off ordering. Use it for binary conversion questions. **When to use conversion**: "What is our trial-to-paid conversion rate?", "What % of visitors sign up?", "What is the lead-to-close rate in the last 30 days?" **When NOT to use conversion**: If you need 3 or more ordered steps with intermediate drop-off analysis, use [`funnel`](./funnel). If you want a time-series count, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | --------------------------- | -------------------------------------------------------------------------- | | `{{denominatorCount}}` | Number of users who fired `denominatorEvent` in the window | | `{{numeratorCount}}` | Number of those users who also fired `numeratorEvent` | | `{{conversionRatePct}}` | Conversion rate as a percentage | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevConversionRatePct}}` | Conversion rate in the previous period (when `hasComparison` is true) | | `{{conversionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/trial-to-paid.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: trial-to-paid displayName: Trial → Paid Conversion Rate description: Percentage of trial starts that convert to a paid subscription within 30 days spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: conversion entity: person_id denominatorEvent: trial_started numeratorEvent: subscription_started conversionWindow: 30d breakdowns: - property: plan maxCardinality: 5 compareWindow: previous_period llm: promptTemplate: | Trial-to-paid conversion for {{windowPeriod}}. {{denominatorCount}} trials started. {{numeratorCount}} converted ({{conversionRatePct}}%). {{#if hasComparison}} Previous period: {{prevConversionRatePct}}% ({{conversionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Identify the primary driver of the conversion rate and recommend one improvement. maxOutputTokens: 400 ``` # Custom Analysis (/docs/react/concepts/insight_trackers/analysis_types/custom) Custom analysis is not available in the AI-assisted tracker builder. Create custom trackers using the YAML editor. Overview [#overview] The `custom` analysis type passes a filtered list of raw events directly to the LLM for freeform analysis. Unlike structured types, it does not run pre-computed queries or inject metric variables — only the matching events and universal base variables are available. Use `custom` when none of the structured types fit your use case. Configuration Reference [#configuration-reference] RawEventsConfig Properties [#raweventsconfig-properties] Available Template Variables [#available-template-variables] `custom` analysis only has access to the universal base variables — no pre-computed metrics: | Variable | Description | | ------------------ | ---------------------------------------------------- | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Raw event list serialised as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/user-engagement.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: user-engagement displayName: User Engagement description: Tracks engagement patterns via raw event inspection spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: custom rawEvents: events: - signup_completed - habit_created - session_started minEvents: 1 maxEvents: 50 llm: promptTemplate: | Analyze user engagement for {{windowPeriod}}. Event data: {{dataAsJson}} Generate a one-sentence insight summarizing engagement patterns. maxOutputTokens: 200 ``` # Feature Adoption (/docs/react/concepts/insight_trackers/analysis_types/feature_adoption) Overview [#overview] Feature Adoption measures what percentage of your **active users** have tried a specific feature at least once during the analysis window. The adoption rate is `unique feature users ÷ total active users in the period`. This is distinct from a raw usage count — it tells you about feature discovery and uptake relative to your active user base. **When to use featureAdoption**: "How many active users have tried the new AI assistant?", "What is the adoption rate of the export feature?", "Is v2 dashboard adoption growing month over month?" **When NOT to use featureAdoption**: If you want a raw time-series count of feature usage, use [`trend`](./trend). If you want a simple rate not tied to the active user base, use [`conversion`](./conversion). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | -------------------------------------------------------------------------- | | `{{activeBaseCount}}` | Total active users in the analysis window | | `{{uniqueAdopters}}` | Users who fired at least one feature event | | `{{adoptionRatePct}}` | Percentage of active users who adopted the feature | | `{{avgUsesPerAdopter}}` | Average number of feature interactions per adopter | | `{{hasComparison}}` | `true` if `compareWindow` was set and previous-period data is available | | `{{prevAdoptionRatePct}}` | Adoption rate in the previous period (when `hasComparison` is true) | | `{{adoptionDeltaPct}}` | Percentage-point change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 30 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/ai-assistant-adoption.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: ai-assistant-adoption displayName: AI Assistant Feature Adoption description: What fraction of active users have tried the AI assistant spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_30d analysis: type: featureAdoption entity: person_id featureEvents: - event: ai_assistant_opened label: Opened AI Assistant - event: ai_suggestion_accepted label: Accepted AI Suggestion activeUserBaseline: event: session_started period: 30d breakdowns: - property: plan maxCardinality: 5 metrics: - adoptionRate - avgUsesPerAdopter - weekOverWeekDelta compareWindow: previous_period llm: promptTemplate: | AI assistant adoption analysis for {{windowPeriod}}. Active user base: {{activeBaseCount}}. Adopters: {{uniqueAdopters}} ({{adoptionRatePct}}%). Average uses per adopter: {{avgUsesPerAdopter}}. {{#if hasComparison}} Previous period: {{prevAdoptionRatePct}}% ({{adoptionDeltaPct}}pp change). {{/if}} Full data: {{dataAsJson}} Describe whether adoption is healthy and suggest one action to increase it. maxOutputTokens: 400 ``` # Funnel Analysis (/docs/react/concepts/insight_trackers/analysis_types/funnel) Overview [#overview] Funnel Analysis tracks how users progress through an **ordered series of steps** and shows exactly where they drop off. Use it whenever the key question is "how many users made it from step A to step B (to step C …)?" and you need to see intermediate drop-off at each stage. **When to use funnel**: Checkout flows, onboarding wizards, trial-to-paid flows, signup sequences, feature setup journeys — any multi-step process where order matters and drop-off location is the insight you care about. **When NOT to use funnel**: If you only need a single A → B rate without step ordering, use [`conversion`](./conversion). If you want a time-series count of step completions, use [`trend`](./trend). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | -------------------------- | ------------------------------------------------------------------ | | `{{totalEntrants}}` | Number of users who completed the first funnel step | | `{{overallConversionPct}}` | Percentage of entrants who completed the final step | | `{{stepsSummary}}` | Step-by-step conversion table (label, count, CVR%) | | `{{worstStep}}` | Label of the step with the highest absolute user loss | | `{{worstStepCvr}}` | Conversion rate (%) at the worst step | | `{{worstStepLoss}}` | Number of users lost at the worst step | | `{{hasBreakdown}}` | `true` if breakdown data is present | | `{{breakdownSummary}}` | Breakdown results table (only present when `hasBreakdown` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/checkout-funnel.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: checkout-funnel displayName: Checkout Funnel Analysis description: Track drop-off across the 4-step checkout flow spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_7d analysis: type: funnel entity: person_id steps: - event: cart_viewed label: Viewed Cart - event: checkout_started label: Started Checkout - event: payment_entered label: Entered Payment - event: order_completed label: Completed Order conversionWindow: 2h breakdowns: - property: plan maxCardinality: 5 llm: promptTemplate: | Analyze this checkout funnel for {{windowPeriod}}. {{totalEntrants}} users entered the funnel. Overall conversion: {{overallConversionPct}}%. Step breakdown: {{stepsSummary}} Worst step: {{worstStep}} ({{worstStepCvr}}% CVR, {{worstStepLoss}} users lost). Full data: {{dataAsJson}} Provide 2-3 actionable recommendations to improve conversion at the weakest step. maxOutputTokens: 500 ``` # Analysis Types (/docs/react/concepts/insight_trackers/analysis_types) Journium trackers use a structured `analysis` block that selects one of nine structured analysis algorithms, plus Custom analysis. Each type determines: * **What queries are compiled** against your event data * **Which template variables** are injected into your `llm.promptTemplate` * **What computed metrics** are surfaced in the insight Choosing the Right Type [#choosing-the-right-type] }> Track ordered step completion and identify where users drop off. }> Cohort return-rate curves over time — D1, D7, D30, and beyond. }> Measure what percentage of new users reach the first value moment. }> Identify users who were active but have since gone silent. }> What fraction of active users have tried a specific feature. }> Automated spike and dip detection vs. a statistical baseline. }> Simple numerator / denominator rate — percentage of group A that does B. }> Compare a metric across cohorts defined by join date or a property value. }> Count events or unique users per time period — daily, weekly, monthly. }> Pass raw matching events to the LLM — not available in the NL Builder. Quick Selection Guide [#quick-selection-guide] | If you want to… | Use type | | ---------------------------------------------------------- | ----------------- | | See where users drop off across an ordered multi-step flow | `funnel` | | Track what fraction of cohorts return at D1 / D7 / D30 | `retention` | | Measure the aha-moment rate for new users | `activation` | | Find users who went quiet and are at risk of churning | `churn` | | Know what fraction of active users have adopted a feature | `featureAdoption` | | Get alerted when a metric spikes or dips anomalously | `anomaly` | | Compute a simple event-A-to-event-B conversion rate | `conversion` | | Compare engagement or revenue across cohort groups | `cohort` | | Plot event counts, DAU, or sums over time | `trend` | | Analyze matching events without pre-computed metrics | `custom` | Universal Template Variables [#universal-template-variables] All analysis types inject these variables into `llm.promptTemplate`: | Variable | Description | | ------------------ | ----------------------------------------------------------------------- | | `{{windowPeriod}}` | Human-readable description of the analysis window, e.g. `"last 7 days"` | | `{{dataAsJson}}` | Full structured analysis result serialised as JSON | | `{{executedAt}}` | ISO 8601 timestamp of when this execution started | Each analysis type also provides its own type-specific variables. See the individual type pages for details. # Retention Analysis (/docs/react/concepts/insight_trackers/analysis_types/retention) Overview [#overview] Retention Analysis measures what fraction of users who first performed an action (e.g., signed up) came back and performed a retention event at specified intervals (Day 1, Day 7, Day 30, etc.). It groups users into cohorts by the period they first acted and plots return rates for each cohort. **When to use retention**: "Are users coming back?", "How sticky is the product?", "Show me D7 and D30 retention after signup" — any question about cohort-based return rates over time. **When NOT to use retention**: If you want to identify who is *currently* inactive or at risk today, use [`churn`](./churn). If you want to measure the first-value-moment rate for new users, use [`activation`](./activation). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ---------------------- | ------------------------------------------------------------------------------------------ | | `{{cohortCount}}` | Number of cohorts included in the analysis | | `{{retentionSummary}}` | Cohort × interval retention matrix (cohort label, size, and return rates at each interval) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/signup-retention.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: signup-retention displayName: Signup Retention (D1 / D7 / D30) description: Weekly cohort retention after signup spec: type: LLM trigger: mode: automatic schedule: weekly window: period: last_90d analysis: type: retention entity: person_id cohortEvent: user_signed_up retentionEvent: session_started cohortPeriod: week intervals: [1, 7, 14, 30] minCohortSize: 20 maxCohorts: 12 llm: promptTemplate: | Analyze signup retention for {{windowPeriod}}. {{cohortCount}} weekly cohorts included. Retention matrix: {{retentionSummary}} Full data: {{dataAsJson}} Identify the cohorts with the best and worst D7 retention, and suggest one actionable improvement for early-session engagement. maxOutputTokens: 400 ``` # Trend / Growth (/docs/react/concepts/insight_trackers/analysis_types/trend) Overview [#overview] Trend Analysis computes a time-series of an aggregated metric bucketed by `hour`, `day`, `week`, or `month`. It covers all growth and usage-frequency questions. "How many times does X happen per period?" is always a trend question. **When to use trend**: "How many users are signing up every month?", "Show me daily active users over the last 90 days", "What is the weekly trend in purchases over the past quarter?" **When NOT to use trend**: If you want automated spike/dip alerts, use [`anomaly`](./anomaly). If you want cohort return curves, use [`retention`](./retention). If you want to compare groups, use [`cohort`](./cohort). Configuration Reference [#configuration-reference] Available Template Variables [#available-template-variables] | Variable | Description | | ------------------------- | ------------------------------------------------------------------------- | | `{{metricName}}` | Human-readable name for the metric (derived from `event` + `aggregation`) | | `{{periodCount}}` | Number of time buckets in the result | | `{{currentPeriodValue}}` | Value in the most recent complete time bucket | | `{{peakPeriod}}` | Label of the time bucket with the highest value | | `{{peakValue}}` | The value at the peak period | | `{{trendDirection}}` | Overall trend direction: `"up"`, `"down"`, or `"flat"` | | `{{trendSummary}}` | Human-readable summary of the trend (e.g. "grew 12% week-over-week") | | `{{hasComparison}}` | `true` if `compareWindow` data is available | | `{{previousPeriodValue}}` | Value in the equivalent previous period (when `hasComparison` is true) | | `{{growthRatePct}}` | Percentage change vs. previous period (when `hasComparison` is true) | | `{{windowPeriod}}` | Human-readable analysis window, e.g. `"last 90 days"` | | `{{dataAsJson}}` | Full structured result as JSON | | `{{executedAt}}` | ISO 8601 execution timestamp | Example [#example] ```yaml title=".journium/trackers/daily-signups-trend.yml" apiVersion: journium.app/v0Beta kind: InsightTracker metadata: name: daily-signups-trend displayName: Daily Signups Trend (WoW) description: Daily signup count with week-over-week comparison spec: type: LLM trigger: mode: automatic schedule: daily window: period: last_30d granularity: day analysis: type: trend entity: person_id event: user_signed_up aggregation: uniqueUsers groupBy: day compareWindow: previous_period llm: promptTemplate: | Daily signup trend for {{windowPeriod}}. Metric: {{metricName}} — {{periodCount}} days. Most recent day: {{currentPeriodValue}} signups. Peak day: {{peakPeriod}} ({{peakValue}} signups). Overall trend: {{trendDirection}}. {{trendSummary}} {{#if hasComparison}} Previous period: {{previousPeriodValue}} total. Growth: {{growthRatePct}}%. {{/if}} Full data: {{dataAsJson}} Summarize the signup trend and highlight any days with unusual volume. maxOutputTokens: 400 ```