# Guide

This guide builds on the SDK quickstart and shows you how to:

* Create new event triggers and event types
* Add event-specific properties
* Log events from your code
* View raw events in tables
* Build funnels to visualize events

## Prerequisites

[Set up Hypertune](https://docs.hypertune.com/getting-started/set-up-hypertune)

## Create new event triggers and event types

Go to the **Flags** view in the dashboard. Click the **+** button in the top-right of the sidebar and select **Flag**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FsLxM7vbrSeM92gzYr6zI%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot.png?alt=media&#x26;token=79851f1d-6e83-466d-97b3-98f754cc7587" alt=""><figcaption></figcaption></figure>

Enter a name, and select **Event trigger** as the type. Enable the toggle to **create matching event types**. Click **Create**, then click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FMv6EHqEN1KtE7r7ERBtv%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D.png?alt=media&#x26;token=c6426d81-6391-4c43-a47a-acccdeebc315" alt=""><figcaption></figcaption></figure>

An **event trigger** is a special kind of flag that has a **Void** return type — it doesn't return a value, but can be called like any other flag.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2Fv7OjWPS3AH75SBDcMvYo%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(1).png?alt=media&#x26;token=84beab76-5b2a-42f7-9443-aa9fee667a48" alt=""><figcaption></figcaption></figure>

When your code calls an event trigger, the **Log event** expression is evaluated, and an event is logged with the configured **Event type** and **Payload**.

By default, the event type is set to the one created automatically with your event trigger. If your event trigger is called `pageView`, the event type will be called `PageViewEvent`, and the payload will be of this type.

The payload contains:

* A `context` field with the `Context` type, automatically set to the top-level `context` you pass to the SDK.
* A `properties` field with a type automatically created with your event trigger. If your event trigger is called `pageView`, it will be called `PageViewEventProperties`. By default, the type is empty, but you can add event-specific properties here, e.g. `href`. You can then pass `properties` as an argument when calling the event trigger from your code.

This setup enables you to log events with both the top-level context you pass to the SDK and extra event-specific properties, with full end-to-end type safety based on your schema.

## Add event-specific properties

Click the arrow next to the selected event type to navigate to it in the **Schema** view.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FNDCCIcIqRwig3dzEtcM3%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(2).png?alt=media&#x26;token=5cf2c01a-9f88-4ed5-94f3-fbc023c7501d" alt=""><figcaption></figcaption></figure>

Then click **Go to type** on the **Properties** field to navigate to the event properties type.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2F2h3QQyS45Q9bOhuBwrd5%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(3).png?alt=media&#x26;token=a0f8b38b-c457-4577-8169-eb2af953604a" alt=""><figcaption></figcaption></figure>

By default, this type has no fields, i.e. there are no event-specific properties.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FZrtWZG5Kn7Y3dSB4pkII%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(4).png?alt=media&#x26;token=72146d41-9809-495d-be35-e10b0bcf44c8" alt=""><figcaption></figcaption></figure>

Click **+ Add**, enter a name for the event property, set its type, and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FMYIttQVxUPQbFCTk61ss%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(5).png?alt=media&#x26;token=4f06454c-cfd7-4c94-bb3c-fc38c78b7dfa" alt=""><figcaption></figcaption></figure>

Click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FNLaVEQiwQ4PIlKZ3zyIJ%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_field_path%3Droot%253EsignUp%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522SignUpEventProperties%2522%252C%2522selectedChildName%2522%253A%2522source%2522%257D%20(6).png?alt=media&#x26;token=c599bea4-5fc4-4eb8-9e90-74bc21ae2f87" alt=""><figcaption></figcaption></figure>

## Log events from your code

Regenerate the client:

{% tabs %}
{% tab title="npm" %}

```bash
npx hypertune
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn hypertune
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm hypertune
```

{% endtab %}
{% endtabs %}

Then use the generated method to call the event trigger and log your event:

{% tabs %}
{% tab title="Client Components" %}
Use the generated `useHypertune` hook:

{% code title="components/ClientComponent.tsx" %}

```tsx
'use client'

import { useEffect } from 'react'
import { useHypertune } from '@/generated/hypertune.react'

export default function ClientComponent() {
  const hypertune = useHypertune()
  const hypertuneIsReady = hypertune.isReady()

  useEffect(() => {
    if (!hypertuneIsReady) {
      return
    }
    hypertune.pageView({
      args: { properties: { href: window.location.href } },
    })
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [hypertuneIsReady])

  return (
    <button
      type="button"
      onClick={() => {
        hypertune.signUp({ args: { properties: {} } })
      }}
    >
      Sign up
    </button>
  )
}
```

{% endcode %}

For events like page views that you want to log immediately after rendering a component:

* First check that the Hypertune SDK is ready with `hypertune.isReady()`.
* Log them inside a `useEffect` with a dependency array that only contains the result of `hypertune.isReady()` so they're only logged once.
  {% endtab %}

{% tab title="Route Handlers" %}
Use the `getHypertune` function:

{% code title="app/api/route.ts" %}

```typescript
import { waitUntil } from '@vercel/functions'
import { NextResponse } from 'next/server'
import getHypertune from '@/lib/getHypertune'

export const runtime = 'edge'

export async function GET() {
  const hypertune = await getHypertune({ isRouteHandler: true })

  hypertune.signUp({ args: { properties: {} } })

  waitUntil(hypertune.flushLogs())

  return NextResponse.json({})
}
```

{% endcode %}

**Notes**

* **Enable remote logging:** By default, [remote logging](https://docs.hypertune.com/sdk-reference/remote-logging) is disabled on Next.js servers because prefetching and caching of pages and layouts can cause logs for flag evaluations, experiment exposures, and analytics events to differ from actual user behaviour. To ensure accuracy, remote logging is enabled by default on the client (in the browser) only. However, since Route Handlers aren't subject to the same prefetching and caching patterns, remote logging is enabled for them by passing `{ isRouteHandler: true }` in the call to `getHypertune`.
* **Flush logs:** `waitUntil(hypertune.flushLogs())` ensures that logs are sent. Without this, logs may still flush in the background, but this isn't guaranteed in serverless environments like Vercel deployments.
  {% endtab %}

{% tab title="Outside of React" %}
See the guide on [using Hypertune outside of React](https://docs.hypertune.com/guides/use-hypertune-outside-of-react).
{% endtab %}
{% endtabs %}

## View raw events in tables

Go to the **Analytics** view in the dashboard. Click the **+** button in the top-right of the sidebar and select **Table**. Enter a name and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2Fa8zr2w8lTMDkQs3mb78G%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D.png?alt=media&#x26;token=442c1688-cc92-4e56-86a6-c5f02ee0cb08" alt=""><figcaption></figcaption></figure>

Click **+ Add query**, select **Event**, select the event type from the dropdown, and click **Add**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FjkOB2B61psusnIosJeXV%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D%20(2).png?alt=media&#x26;token=82ccf2ee-2c4f-4922-9f05-a408bc66c25d" alt=""><figcaption></figcaption></figure>

You'll see a table of raw events. To filter them, click **+ Filter**, and configure a filter.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FTSLw9MNKALoYb4cc5lKS%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486.png?alt=media&#x26;token=e675c0fc-fc9d-4db7-ad16-b0c22d401826" alt=""><figcaption></figcaption></figure>

Click **Save** so you can revisit this table and share it with your team.

## Build funnels to visualize events

Click the **+** button in the top-right of the sidebar. Select **Funnel**, enter a name, and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FWY0E6YGgCwhJ97TvHv8H%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486%20(1).png?alt=media&#x26;token=9a650e3a-0d5c-4070-adb7-03fd83a2fe90" alt=""><figcaption></figcaption></figure>

Click **+ Add funnel step**, choose **Event**, select the first event type of your funnel, and click **Add**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FgdiPBeS0UmXsJ393mI9v%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486%20(2).png?alt=media&#x26;token=11bfb93f-a438-48f8-a517-4131cc229dd5" alt=""><figcaption></figcaption></figure>

You'll see the total number of events of that type during the selected time range.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2Fv5vTiBpRXJ3n7kBQyyuZ%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486%20(3).png?alt=media&#x26;token=35d5eb7e-7eeb-498a-a0ba-37902788cb03" alt=""><figcaption></figcaption></figure>

Click the **+** button to the right of the first step, choose **Event**, select your conversion event in the dropdown, and click **Add**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FOiysVS4cKIsa8QFnWrXi%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486%20(4).png?alt=media&#x26;token=765933ee-77e9-4c80-99c1-dfd67bba3b41" alt=""><figcaption></figcaption></figure>

Now you'll see:

* Total number of users who completed the first event during the selected time range
* Number of those users who completed the conversion event during the selected time range
* Conversion rate

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FEWP9xb7r1gimYFuWJu9X%2Flocalhost_3000_projects_6715_main_draft_analytics_setup%3D0%26selected_field_path%3Droot%253EsignUp%26analytics_from%3D2025-09-12T23%253A00%253A00.000Z%26analytics_to%3D2025-10-12T22%253A59%253A59.999Z%26analytics_view_id%3D486%20(5).png?alt=media&#x26;token=ede5e209-90e1-4b46-a8b3-9ea7ef854be1" alt=""><figcaption></figcaption></figure>

Click **Save** so you can revisit this funnel and share it with your team.

## Next steps

* Add more steps to your [funnel](https://docs.hypertune.com/concepts/funnels) or configure each step with filters, breakdowns, segments, derived fields, and aggregations.
* Create an [A/B/n test](https://docs.hypertune.com/concepts/a-b-n-tests) to see if a new feature drives conversion lift across your funnel.
* Run a [multivariate test](https://docs.hypertune.com/concepts/multivariate-tests) to find the best combination of feature variants to maximize conversion lift.
* Set up an [AI loop](https://docs.hypertune.com/concepts/ai-loops) to automatically shift traffic to the best feature variants for each unique user to maximize conversion lift.
