Build customer-facing analytics

This guide shows how to build a customer-facing analytics feature where each user sees their own personalized stats. We'll track button clicks per user and query personalized counts from a PostHog endpoint.

Customer-facing analytics demo app
Prerequisites

Before starting, make sure a PostHog SDK is installed in your app.

Step 1: Create an endpoint with a user variable

Open the SQL editor and write this query:

SQL
SELECT count() as click_count
FROM events
WHERE event = 'hedgehog_clicked'
AND properties.user_id = {variables.user_id}

In the Variables tab, add a variable named user_id with type String.

Create the endpoint with the name hedgehog_clicks_by_user.

Step 2: Track events with user context

When tracking events, include a user_id property to associate them with specific users:

TSX
posthog.capture("hedgehog_clicked", {
user_id: currentUser.id,
});

Step 3: Query the endpoint from your backend

Keep API keys server-side

Never expose your PostHog API key in client-side code. Always proxy endpoint calls through your backend.

Create an API route that queries the endpoint with the user's ID:

TypeScript
// Example: Next.js API route
export async function POST(request: Request) {
const { user_id } = await request.json();
const response = await fetch(
`https://us.posthog.com/api/projects/${PROJECT_ID}/endpoints/hedgehog_clicks_by_user/run`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.POSTHOG_API_KEY}`,
},
body: JSON.stringify({
variables: { user_id },
}),
}
);
const data = await response.json();
return Response.json({ click_count: data.results?.[0]?.[0] ?? 0 });
}

Then fetch from your frontend:

TSX
const response = await fetch("/api/hedgehog-clicks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ user_id: currentUser.id }),
});
const { click_count } = await response.json();

Security considerations

  1. Never expose API keys client-side - Always proxy through your backend
  2. Variables are required - Endpoints with variables require values, preventing accidental data leaks
  3. Validate user IDs - In production, verify the user is authorized to query data for the requested user_id

Next steps

Community questions

Was this page useful?

Questions about this page? or post a community question.