> ## Documentation Index
> Fetch the complete documentation index at: https://speakeasy-20cf8bdf.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Appwrite

> Learn how to track lead conversion events with Appwrite and Dub

When it comes to conversion tracking, a `lead` event happens when a user performs an action that indicates interest in your product or service. This could be anything from:

* Signing up for an account
* Adding a product to cart
* Joining a mailing list

<Frame>
  <img className="rounded-lg border border-gray-100" src="https://assets.dub.co/help/conversion-lead-event.png" alt="A diagram showing how lead events are tracked in the conversion funnel" />
</Frame>

In this guide, we will be focusing on tracking new user sign-ups for a SaaS application that uses Appwrite for user authentication.

## Prerequisites

Before you get started, make sure you follow the [Dub Conversions quickstart guide](/conversions/quickstart) to get Dub Conversions set up for your links:

1. [Enable conversion tracking for your links](/conversions/quickstart#step-1-enable-conversion-tracking-for-your-links)
2. [Install the @dub/analytics client-side SDK](/sdks/client-side/introduction)
3. [Install the Dub server-side SDK](/conversions/quickstart#step-3-install-the-dub-server-side-sdk)

## Configure Appwrite

Next, configure Appwrite to track lead conversion events during the sign up process.

<Steps>
  <Step title="Create an Appwrite Cloud project">
    Head to [Appwrite Cloud](https://apwr.dev/appwrite-dub) and create a new project.

    <Frame>
      <img src="https://mintcdn.com/speakeasy-20cf8bdf/-Y0j4C06SQOILvRL/images/conversions/appwrite/appwrite-new-project.png?fit=max&auto=format&n=-Y0j4C06SQOILvRL&q=85&s=d59f6864619a6a4598bd8f2156ca1c77" alt="New project on Appwrite Cloud" width="1440" height="1024" data-path="images/conversions/appwrite/appwrite-new-project.png" />
    </Frame>

    Create a new API key with the `sessions.write` scope enabled and save the API key for later use. You can also copy your project ID and endpoint from the project's Settings page.

    <Frame>
      <img src="https://mintcdn.com/speakeasy-20cf8bdf/-Y0j4C06SQOILvRL/images/conversions/appwrite/appwrite-api-key.png?fit=max&auto=format&n=-Y0j4C06SQOILvRL&q=85&s=673d629371a24e3315caf9eaf9c1c8b8" alt="API key in your project on Appwrite Cloud" width="1440" height="1024" data-path="images/conversions/appwrite/appwrite-api-key.png" />
    </Frame>

    Then, in your Next.js app, install the Appwrite Node.js SDK.

    ```bash theme={null}
    npm i node-appwrite
    ```
  </Step>

  <Step title="Add environment variables">
    Add the following environment variables to your app.

    ```bash theme={null}
    NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
    NEXT_PUBLIC_APPWRITE_PROJECT=<APPWRITE_PROJECT_ID>
    NEXT_APPWRITE_KEY=<APPWRITE_API_KEY>
    NEXT_DUB_API_KEY=<DUB_API_KEY>
    ```
  </Step>

  <Step title="Integrate Dub Analytics">
    Add the `DubAnalytics` component from the `@dub/analytics` package to your app’s root layout.

    ```tsx src/app/layout.tsx theme={null}
    import type { Metadata } from 'next';
    import { Analytics as DubAnalytics } from '@dub/analytics/react';

    export const metadata: Metadata = {
      title: 'Appwrite Dub Leads Example',
      description: 'Appwrite Dub Leads Tracking example app with Next.js'
    };

    export default function RootLayout({
      children
    }: Readonly<{
      children: React.ReactNode;
    }>) {
      return (
        <html lang="en">
          <body>{children}</body>
          <DubAnalytics />
        </html>
      );
    }
    ```
  </Step>

  <Step title="Prepare the Appwrite client and auth library">
    Create the Appwrite Session and Admin client (necessary for SSR apps, as explained in the [Appwrite docs](https://appwrite.io/docs/products/auth/server-side-rendering)). Additionally, create a function to verify user login.

    ```ts src/lib/server/appwrite.ts theme={null}
    'use server';
    import { Client, Account } from 'node-appwrite';
    import { cookies } from 'next/headers';

    export async function createSessionClient() {
      const client = new Client()
        .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT as string)
        .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT as string);

      const session = (await cookies()).get('my-custom-session');
      if (!session || !session.value) {
        throw new Error('No session');
      }

      client.setSession(session.value);

      return {
        get account() {
          return new Account(client);
        }
      };
    }

    export async function createAdminClient() {
      const client = new Client()
        .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT as string)
        .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT as string)
        .setKey(process.env.NEXT_APPWRITE_KEY as string);

      return {
        get account() {
          return new Account(client);
        }
      };
    }
    ```
  </Step>

  <Step title="Set up Dub SDK">
    Create the Dub client and send leads to Dub using the `dub.track.lead()` function.

    ```ts src/lib/server/dub.ts theme={null}
    import type { Models } from 'node-appwrite';
    import { Dub } from 'dub';

    const dub = new Dub({
      token: process.env.NEXT_DUB_API_KEY
    });

    export function addDubLead(user: Models.User<Models.Preferences>, dub_id: string) {
      dub.track.lead({
        clickId: dub_id,
        eventName: 'Sign Up',
        externalId: user.$id,
        customerName: user.name,
        customerEmail: user.email
      });
    }
    ```
  </Step>

  <Step title="Send leads to Dub on user signup">
    In the `/auth` page, use the Appwrite Admin client to allow users to sign up. Post sign up, check if the `dub_id` cookie is present, send a lead event to Dub if found, and delete the `dub_id` cookie.

    ```tsx src/app/auth/page.tsx theme={null}
    import { ID } from 'node-appwrite';
    import { createAdminClient, getLoggedInUser } from '@/lib/server/appwrite';
    import { cookies } from 'next/headers';
    import { redirect } from 'next/navigation';
    import { addDubLead } from '@/lib/server/dub';

    async function signUpWithEmail(formData: any) {
      'use server';

      // Get sign up info from form
      const email = formData.get('email');
      const password = formData.get('password');
      const name = formData.get('name');

      // Create account and session using Appwrite
      const { account } = await createAdminClient();

      const user = await account.create(ID.unique(), email, password, name);
      const session = await account.createEmailPasswordSession(email, password);

      (await cookies()).set('my-custom-session', session.secret, {
        path: '/',
        httpOnly: true,
        sameSite: 'strict',
        secure: true
      });

      // Check if Dub ID is present in cookies and track lead if found
      const dub_id = (await cookies()).get('dub_id')?.value;
      if (dub_id) {
        addDubLead(user, dub_id);
        (await cookies()).delete('dub_id');
      }

      // Redirect to success page
      redirect('/auth/success');
    }

    export default async function SignUpPage() {

      // Verify active user session and redirect to success page if found
      const user = await getLoggedInUser();
      if (user) redirect('/auth/success');

      return (
        <>
          <form action={signUpWithEmail}>
            <input id="email" name="email" placeholder="Email" type="email" required />
            <input id="password" name="password" placeholder="Password" minLength={8} type="password" required />
            <input id="name" name="name" placeholder="Name" type="text" required />
            <button type="submit">Sign up</button>
          </form>
        </>
      );
    }
    ```
  </Step>
</Steps>

Here's the full list of attributes you can pass when sending a lead event:

| Property         | Required | Description                                                                                                              |
| :--------------- | :------- | :----------------------------------------------------------------------------------------------------------------------- |
| `clickId`        | **Yes**  | The unique `dub_id` parameter that the lead conversion event is attributed to.                                           |
| `eventName`      | **Yes**  | The name of the event. Example: "Sign up".                                                                               |
| `externalId`     | **Yes**  | The unique ID of the customer in your system. Will be used to identify and attribute all future events to this customer. |
| `customerEmail`  | No       | The email address of the customer. If not passed, a random email address will be generated.                              |
| `customerName`   | No       | The name of the customer. If not passed, a random name will be generated (e.g. "Big Red Caribou").                       |
| `customerAvatar` | No       | The avatar URL of the customer. If not passed, a random avatar URL will be generated.                                    |

## Example App

To learn more about how to track leads with Appwrite, check out the following example app:

<Card title="Appwrite + Dub Next.js  Example" icon="github" href="https://github.com/appwrite-community/appwrite-dub-next">
  See how to track new user sign-ups with Appwrite and the Dub SDK.
</Card>

## View your conversions

Once you've enabled conversion tracking for your links, all your tracked conversions will show up on your [Analytics dashboard](https://app.dub.co/analytics). We provide 3 different views to help you understand your conversions:

* **Time-series**: A [time-series view](https://dub.co/help/article/dub-analytics#1-time-series-analytics-chart) of the number clicks, leads and sales.

<Frame>
  <img src="https://mintcdn.com/speakeasy-20cf8bdf/-Y0j4C06SQOILvRL/images/conversions/timeseries-chart.png?fit=max&auto=format&n=-Y0j4C06SQOILvRL&q=85&s=7d752129ab0f59fb7ac44b5c83d608c9" alt="Time-series line chart" width="1600" height="900" data-path="images/conversions/timeseries-chart.png" />
</Frame>

* **Funnel chart**: A funnel chart view visualizing the conversion & dropoff rates across the different steps in the conversion funnel (clicks → leads → sales).

<Frame>
  <img src="https://mintcdn.com/speakeasy-20cf8bdf/-Y0j4C06SQOILvRL/images/conversions/funnel-chart.png?fit=max&auto=format&n=-Y0j4C06SQOILvRL&q=85&s=bd252526bae397088168478a8097c10d" alt="Funnel chart view showing the conversion & dropoff rates from clicks → leads → sales" width="1600" height="900" data-path="images/conversions/funnel-chart.png" />
</Frame>

* **Real-time events stream**: A [real-time events stream](https://dub.co/help/article/real-time-events-stream) of every single conversion event that occurs across all your links in your workspace.

<Frame>
  <img src="https://mintcdn.com/speakeasy-20cf8bdf/-Y0j4C06SQOILvRL/images/conversions/events-table.png?fit=max&auto=format&n=-Y0j4C06SQOILvRL&q=85&s=256bd06254e543c40f1ae268424e17e1" alt="The Events Stream dashboard on Dub" width="1600" height="900" data-path="images/conversions/events-table.png" />
</Frame>
