# Build customer-facing analytics - Docs

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](https://res.cloudinary.com/dmukukwp6/image/upload/w_1000,c_limit,q_auto,f_auto/pasted_image_2026_02_09_T10_05_55_325_Z_015ac1dc57.png)![Customer-facing analytics demo app](https://res.cloudinary.com/dmukukwp6/image/upload/w_1000,c_limit,q_auto,f_auto/pasted_image_2026_02_09_T10_05_16_736_Z_2d8553ca7b.png)

**Prerequisites**

Before starting, make sure [a PostHog SDK is installed](/docs/getting-started/install.md) in your app.

## Step 1: Create an endpoint with a user variable

Open the [SQL editor](https://us.posthog.com/sql) and write this query:

SQL

[Run in PostHog](https://us.posthog.com/sql?open_query=SELECT+count%28%29+as+click_count%0AFROM+events%0AWHERE+event+%3D+'hedgehog_clicked'%0A++AND+properties.user_id+%3D+%7Bvariables.user_id%7D)

PostHog AI

```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 AI

```jsx
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

PostHog AI

```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

PostHog AI

```jsx
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

-   [Materialize your endpoint](/docs/endpoints/materialization.md) for faster response times
-   [Generate a typed SDK](/docs/endpoints/openapi-sdk-generation.md) for type-safe API calls
-   Learn about [caching](/docs/endpoints/caching.md) to reduce costs

### Community questions

Ask a question

### Was this page useful?

HelpfulCould be better