# Convalytics Agent Skill Add analytics to a Convex project: web analytics (page views, sessions, bounce rate) + product analytics (event tracking from mutations/actions). ## Learn more - Full product manual: https://convalytics.dev/llms-full.txt - OpenAPI spec: https://convalytics.dev/openapi.json - Agent card: https://convalytics.dev/.well-known/agent-card.json - Dashboard: https://convalytics.dev ## When to use this skill Use when the user asks to: - Add analytics / event tracking to a Convex project - Track user signups, purchases, feature usage, or other product events - Set up page view analytics - Integrate Convalytics ## Prerequisites - A Convex project (has `convex/` directory and `convex` in dependencies) - Authenticated with Convex (`npx convex dev` has been run before; this is already the case if the project is actively being developed) - No Convalytics account or write key needed. The CLI auto-provisions one. --- ## First: ask the user what they want Convalytics has two products. Ask the user before starting: - **(A) Web analytics only:** automatic page views, sessions, bounce rate, referrers. Just a script tag, no Convex component needed. - **(B) Web analytics + product analytics:** everything in A, plus custom event tracking from mutations/actions (signups, payments, feature usage). If the user only wants web analytics, skip the event discovery and instrumentation steps below. --- ## Workflow ### 1. Install Run the CLI. No write key required. It auto-provisions a project and returns a claim link for the human: ```bash npx convalytics init ``` If the user already has a write key, pass it directly: ```bash npx convalytics init YOUR_WRITE_KEY ``` This handles: package install, config patching, writing `convex/analytics.ts` with the write key inlined, browser script tag, and agent skill file. No Convex environment variables are set. The write key is safe to commit (it also ships in the browser script tag) and the deployment is auto-detected at runtime from `CONVEX_CLOUD_URL`. The CLI outputs a **claim URL**. Share it with the user so they can connect the project to their Convalytics account. Events flow immediately, before claiming. If `index.html` wasn't found (Next.js, Astro, etc.), add the script tag to the `
` manually: ```html ``` - Next.js: add to `app/layout.tsx` or use `next/script` with `strategy="afterInteractive"` - Astro: add to your base layout **Important:** After setup, let the user know that the changes are **local only**. Web analytics won't collect data in production until these changes are committed and deployed. Ask the user if they'd like you to commit and deploy, or if they'd prefer to handle it themselves. **If the user chose (A) web analytics only, you're done.** Share the claim URL, let them know the changes need to be committed and deployed to go live, and stop here. ### 2. Discover what to track (option B only) There are **two types** of events to instrument. Propose both in a single tracking plan: #### Server-side events (Convex mutations/actions) Read `convex/schema.ts` and every file in `convex/` to understand the data model and business logic. Identify every mutation and action that represents a meaningful user action (signups, payments, data changes, API calls). #### Browser-side events (UI interactions) Read the frontend components (`src/`, `app/`, etc.) and identify meaningful UI interactions that don't trigger a mutation: button clicks, navigation, feature discovery, form interactions, expanding/collapsing UI, selecting options. These are tracked directly in the browser without needing a Convex mutation wrapper. #### Propose a combined tracking plan For each event include: - **Event name**: `snake_case`, `noun_verb` format (e.g. `user_signed_up`) - **Type**: `server` or `browser` - **File**: which file contains the mutation/action or React component - **Function/Component**: which exported function or component to instrument - **Props**: what metadata to attach Example output: ``` Proposed tracking plan: Server-side events (convex mutations/actions): 1. user_signed_up (convex/users.ts → createUser), props: { plan } 2. subscription_started (convex/billing.ts → createSubscription), props: { plan, interval } 3. payment_succeeded (convex/stripe.ts → handleWebhook), props: { amount, currency } 4. message_sent (convex/messages.ts → sendMessage), props: { channel } Browser-side events (UI interactions): 5. pricing_plan_clicked (src/components/PricingTable.tsx), props: { plan } 6. feature_explored (src/pages/Dashboard.tsx), props: { feature } 7. settings_changed (src/pages/Settings.tsx), props: { setting, value } ``` Guidelines: - Prefix AI-related events with `ai_` (e.g. `ai_completion_requested`) - Don't over-track. Aim for 5–15 events total across both types that capture the core user journey. - Skip internal/admin/migration functions - **NEVER call `analytics.track()` inside a `query`.** Queries don't support mutations and will crash. Only use `track()` in `mutation` or `action` handlers. - Skip read-only queries; only track mutations and actions that represent user intent - Use browser-side tracking for interactions that don't write data (clicks, navigation, UI exploration) - Use server-side tracking for events where transactional context matters (payments, signups, data mutations) **Wait for the user to approve the plan before instrumenting.** ### 3. Instrument approved events **Server-side events:** add a tracking call in the mutation/action, right after the core logic. If the app has auth, include `userEmail` for human-readable display in the dashboard: ```typescript import { analytics } from "./analytics"; export const createUser = mutation({ args: { name: v.string(), email: v.string(), plan: v.string() }, handler: async (ctx, args) => { const userId = await ctx.db.insert("users", args); const identity = await ctx.auth.getUserIdentity(); await analytics.track(ctx, { name: "user_signed_up", userId: String(userId), userEmail: identity?.email, props: { plan: args.plan }, }); return userId; }, }); ``` **Important:** Use the `userEmail` field (not `props.email`); it's a first-class field that the dashboard shows in the User column. Putting email in `props` will NOT display it as the user identifier. **Browser-side events:** call `convalytics.track()` directly in the React component. No import needed; it's a global from the script tag: ```typescript function PricingCard({ plan }: { plan: string }) { return ( ); } ``` ### 4. Wire up user identity (apps with auth only) If the app has user authentication, add two calls so page views and browser events show the real user instead of an anonymous UUID: **After sign-in** (e.g. in the auth callback, session provider, or a `useEffect` that fires when the user is available): ```typescript convalytics.identify(user.id, { email: user.email, name: user.name }) ``` **On sign-out:** ```typescript convalytics.reset() ``` This is critical for apps with auth. Without it, all browser-side page views and events will show anonymous UUIDs even for logged-in users. ### 5. Commit and deploy All the changes from setup and instrumentation are local. Events won't flow in production until **both** of these ship: 1. **Frontend deploy** (whatever the project uses: `git push`, `vercel deploy`, etc.). Delivers the script tag that captures page views. 2. **Convex backend deploy.** Delivers the `convex/analytics.ts` component and any `analytics.track()` calls you instrumented. This is a **separate step** from your frontend deploy: ```bash npx convex deploy ``` If you push to git and only the frontend auto-deploys, your Convex prod deployment will still be running the old code with no tracking. Events will fire from dev but silently drop in prod. **If deploying Convex from CI** (e.g. Vercel, GitHub Actions): set `CONVEX_DEPLOY_KEY` in the CI environment and use `npx convex deploy --cmd '