Direct sale tracking

Discover how to track sales without first recording a lead event in LinkKit.

Discover how to track sales without first recording a lead event in LinkKit.

Business Plan Requirement
This feature is only available on LinkKit Business plans and above.

When tracking conversions, a sale event occurs when a customer completes a revenue-generating action involving your product or service. Common examples include:

  • Subscribing to a paid plan
  • Upgrading from one plan or tier to another
  • Purchasing a product from your online store

These events represent completed transactions and help measure the revenue generated from your marketing and referral efforts.

Track Sales Without a Prior Lead Event

In this guide, we'll cover how to track sales conversion events directly in LinkKit without first recording a lead event. This is useful when you want to attribute a sale directly to a click, without requiring users to pass through a separate lead-tracking stage.

When to Use Direct Sale Tracking

Direct sale tracking is ideal when:

  • Lead tracking isn't necessary, such as with one-time purchases or simple checkout flows.
  • You want to attribute sales directly to clicks, without tracking intermediate conversion steps.
  • Customers can make a purchase without creating an account, signing up, or becoming a tracked lead first.

By using direct sale tracking, you can simplify your conversion workflow while still maintaining accurate click-to-sale attribution in LinkKit.

Alternative Tracking Methods
If you're tracking both leads and sales in your conversion funnel, refer to the server-side tracking or client-side tracking guides instead.
Lead Commission Rewards
Lead commission rewards are not generated when using direct sale tracking.

Prerequisites

Before you can begin tracking sales conversions, you'll need to enable conversion tracking for your LinkKit links.

Once conversion tracking is enabled, LinkKit will be able to attribute sales events to the clicks that drove them and accurately measure conversion performance.

LinkKit Partners
If you're using LinkKit Partners, you can skip this step, as conversion tracking is enabled by default for all partner links.
Option 1: Enable Conversion Tracking at the Workspace Level
To automatically enable conversion tracking for all new links created within a workspace:

Navigate to your workspace's Tracking Settings page.
Turn on the Workspace Conversion Tracking toggle.

Once enabled, conversion tracking will be applied to all future links created in that workspace, ensuring that new links are ready for conversion attribution by default.
Option 2: Enable Conversion Tracking for Individual Links
If you prefer not to enable conversion tracking across your entire workspace, you can activate it on a per-link basis.

To enable conversion tracking for a specific link:

Open the LinkKit Link Builder for the link you want to track.
Enable the Conversion Tracking toggle.

This will turn on conversion tracking only for that link, allowing you to selectively track conversions where needed.
Option 3: Enable Conversion Tracking via the API
You can also enable conversion tracking programmatically using the LinkKit API.

When creating or updating a link, simply include the trackConversion: true parameter in your API request. This will enable conversion tracking for that link automatically.

Next, you'll need to install the LinkKit Analytics script and configure the required settings for client-side conversion tracking.

1. Allowlist Your Website Domain

To allow client-side conversion events to be captured by LinkKit, you’ll need to add your website domain to the allowlist.

To do this:

  • Go to your workspace's Tracking Settings page.
  • Add your website domain to the Allowed Hostnames list.

This adds an extra layer of security by ensuring that only approved domains can send conversion events using your publishable key.

You can use hostname patterns to group domains when adding them to the allowlist:

  • example.com – Tracks conversion events only from the main domain (example.com).
  • *.example.com – Tracks conversion events from all subdomains of example.com, but not from the main domain itself.
Local Testing with Hostnames
When testing locally, you can temporarily add localhost to the Allowed Hostnames list to allow local events to be captured by LinkKit. Remove it from the list once your site is ready to go live.

Generate Your Publishable Key

Before you can start tracking client-side conversions, you’ll need to generate a publishable key from your LinkKit workspace.

To generate a publishable key:

  • Navigate to your workspace's Tracking Settings page.
  • Go to the Publishable Key section.
  • Generate a new publishable key.

Once generated, this key can be used to configure client-side conversion tracking on your website.

3. Install the LinkKit Analytics Script

Next, add the LinkKit Analytics script to your website or web application to enable client-side conversion tracking.

You can install the LinkKit Analytics script using several different methods depending on your website setup:

Publishable Key Configuration
You must configure the publishable key generated in Step 1 when installing the LinkKit analytics script. Without this key, client-side conversion tracking will not work.
<script>
  !(function (c, n) {
    c[n] =
      c[n] ||
      function () {
        (c[n].q = c[n].q || []).push(arguments);
      };
    ["trackClick", "trackLead", "trackSale"].forEach(
      (t) => (c[n][t] = (...a) => c[n](t, ...a)),
    );
    var s = document.createElement("script");
    s.defer = 1;
    s.src = "https://www.linkkitcdn.com/analytics/script.conversion-tracking.js";
    s.setAttribute("data-publishable-key", "linkkit_pk_xxxxxxxx"); // Replace with your publishable key
    document.head.appendChild(s);
  })(window, "linkkitAnalytics");
</script>
import { Analytics as LinkKitAnalytics } from '@linkkit/analytics/react';

export default function RootLayout({
  children,
}) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
      <LinkKitAnalytics
        ...
        publishableKey="linkkit_pk_xxxxxxxx" // Replace with your publishable key
      />
    </html>
  );
}

Track Direct Sale Conversions

To track a direct sale conversion, include the clickId parameter along with customer details when sending the sale event.

The clickId value can be retrieved from the linkkit_id cookie, which is automatically created when a user clicks on your LinkKit link. This allows LinkKit to attribute the sale back to the original click.

Track Direct Sales Using URL Query Parameters

If users are redirected to a confirmation or thank-you page after completing a purchase, you can track direct sales by retrieving the required query parameters from the URL along with the linkkit_id cookie.

This allows you to capture purchase information and correctly attribute the sale conversion to the original link click.

import { useAnalytics } from "@linkkit/analytics/react";
import { useEffect } from "react";

// Helper function to read cookie
function getCookie(name: string) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop()?.split(";").shift();
}

export function OrderConfirmationPage() {
  const { trackSale } = useAnalytics();

  useEffect(() => {
    // Get query parameters from URL
    const params = new URLSearchParams(window.location.search);
    const customerId = params.get("customer_id");
    const amount = params.get("amount");
    const invoiceId = params.get("invoice_id");

    // Get click ID from cookie
    const clickId = getCookie("linkkit_id");

    if (customerId && amount && clickId) {
      // Track the direct sale event
      trackSale({
        eventName: "Purchase",
        customerExternalId: customerId,
        amount: parseInt(amount), // Amount in cents
        invoiceId: invoiceId || undefined,

        // Required for direct sale tracking:
        clickId: clickId,
        customerName: "John Doe", // Optional: customer name
        customerEmail: "john@example.com", // Optional: customer email
        customerAvatar: "https://example.com/avatar.jpg", // Optional: avatar URL
      });
    }
  }, [trackSale]);

  return <div>Thank you for your purchase!</div>;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Order Confirmation</title>
  </head>
  <body>
    <div>Thank you for your purchase!</div>

    <script>
      // Helper function to read cookie
      function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(";").shift();
      }

      // Get query parameters from URL
      const params = new URLSearchParams(window.location.search);
      const customerId = params.get("customer_id");
      const amount = params.get("amount");
      const invoiceId = params.get("invoice_id");

      // Get click ID from cookie
      const clickId = getCookie("linkkit_id");

      if (customerId && amount && clickId) {
        // Track the direct sale event
        linkkitAnalytics.trackSale({
          eventName: "Purchase",
          customerExternalId: customerId,
          amount: parseInt(amount), // Amount in cents
          invoiceId: invoiceId || undefined,

          // Required for direct sale tracking:
          clickId: clickId,
          customerName: "John Doe", // Optional: customer name
          customerEmail: "john@example.com", // Optional: customer email
          customerAvatar: "https://example.com/avatar.jpg", // Optional: avatar URL
          currency: "usd",
          paymentProcessor: "stripe",
          metadata: { plan: "pro" },
        });
      }
    </script>
  </body>
</html>

Track Direct Sales from Form Submissions

You can also track direct sale conversions when users complete a checkout or purchase form on your website.

By capturing the required customer and transaction details from the form submission, you can send the sale event to LinkKit and attribute the conversion back to the original click.

import { useAnalytics } from "@linkkit/analytics/react";
import { useState } from "react";

// Helper function to read cookie
function getCookie(name: string) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop()?.split(";").shift();
}

export function CheckoutForm() {
  const { trackSale } = useAnalytics();

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Get click ID from cookie
    const clickId = getCookie("linkkit_id");

    if (clickId) {
      // Track the direct sale event
      trackSale({
        eventName: "Purchase",
        customerExternalId: "cus_RBfbD57H",
        amount: 5000, // $50.00
        invoiceId: "in_1MtHbELkdIwH",

        // Required for direct sale tracking:
        clickId: clickId,
        customerName: "John Doe",
        customerEmail: "john@example.com",
        customerAvatar: "https://example.com/avatar.jpg",
      });
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      ...
      <button type="submit">Complete Purchase</button>
    </form>
  );
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Checkout</title>
  </head>
  <body>
    <form id="checkoutForm">
      ...
      <button type="submit">Complete Purchase</button>
    </form>

    <script>
      // Helper function to read cookie
      function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(";").shift();
      }

      document
        .getElementById("checkoutForm")
        .addEventListener("submit", function (e) {
          e.preventDefault();

          // Get click ID from cookie
          const clickId = getCookie("linkkit_id");

          if (clickId) {
            // Track the direct sale event
            linkkitAnalytics.trackSale({
              eventName: "Purchase",
              customerExternalId: "cus_RBfbD57H",
              amount: 5000, // $50.00
              invoiceId: "in_1MtHbELkdIwH",

              // Required for direct sale tracking:
              clickId: clickId,
              customerName: "John Doe",
              customerEmail: "john@example.com",
              customerAvatar: "https://example.com/avatar.jpg",
              currency: "usd",
              paymentProcessor: "stripe",
              metadata: { plan: "pro" },
            });
          }
        });
    </script>
  </body>
</html>

Server-Side Direct Sale Tracking

You can also track direct sales from your backend by including the clickId parameter when sending a sale event through the LinkKit API.

This allows you to attribute sales directly to the original click while processing conversion events securely on the server side.

import { LinkKit } from "linkkit";

const linkkit = new LinkKit();

await linkkit.track.sale({
  customerExternalId: "cus_RBfbD57HDzPKpduI8elr5qHA",
  amount: 5000,
  paymentProcessor: "stripe",
  eventName: "Purchase",
  invoiceId: "in_1MtHbELkdIwH",
  currency: "usd",

  // Required for direct sale tracking:
  clickId: "cm3w...", // Pass the click ID from your frontend
  customerName: "John Doe",
  customerEmail: "john@example.com",
  customerAvatar: "https://example.com/avatar.jpg",
});
from linkkit import LinkKit
import os

linkkit = LinkKit(token=os.environ['LINKKIT_API_KEY'])

linkkit.track.sale({
    'external_id': 'cus_RBfbD57HDzPKpduI8elr5qHA',
    'amount': 5000,
    'payment_processor': 'stripe',
    'event_name': 'Purchase',
    'invoice_id': 'in_1MtHbELkdIwH',
    'currency': 'usd',

    # Required for direct sale tracking:
    'click_id': 'cm3w...', # Pass the click ID from your frontend
    'customer_name': 'John Doe',
    'customer_email': 'john@example.com',
    'customer_avatar': 'https://example.com/avatar.jpg'
})
package main

import (
    "context"
    linkkit "github.com/linkkit/linkkit-go"
)

d := linkkit.New(
    linkkit.WithSecurity(os.Getenv("LINKKIT_API_KEY")),
)

_, err := d.Track.Sale(context.Background(), &operations.TrackSaleRequest{
    CustomerExternalId: "cus_RBfbD57HDzPKpduI8elr5qHA",
    Amount:             5000,
    PaymentProcessor:   "stripe",
    EventName:          "Purchase",
    InvoiceId:          "in_1MtHbELkdIwH",
    Currency:           "usd",

    // Required for direct sale tracking:
    ClickId:         "cm3w...", // Pass the click ID from your frontend
    CustomerName:    "John Doe",
    CustomerEmail:   "john@example.com",
    CustomerAvatar:  "https://example.com/avatar.jpg",
})
require 'linkkit'

linkkit = ::OpenApiSDK::LinkKit.new
linkkit.config_security(
  ::OpenApiSDK::Shared::Security.new(
    token: ENV['LINKKIT_API_KEY']
  )
)

req = ::OpenApiSDK::Operations::TrackSaleRequest.new(
  external_id: 'cus_RBfbD57HDzPKpduI8elr5qHA',
  amount: 5000,
  payment_processor: 'stripe',
  event_name: 'Purchase',
  invoice_id: 'in_1MtHbELkdIwH',
  currency: 'usd',

  # Required for direct sale tracking:
  click_id: 'cm3w...', # Pass the click ID from your frontend
  customer_name: 'John Doe',
  customer_email: 'john@example.com',
  customer_avatar: 'https://example.com/avatar.jpg'
)

linkkit.track.sale(req)
<?php

require 'vendor/autoload.php';

use LinkKit\LinkKit;
use LinkKit\Models\Operations;

$linkkit = LinkKit::builder()->setSecurity($_ENV["LINKKIT_API_KEY"])->build();

$request = new Operations\TrackSaleRequest();
$request->customerExternalId = 'cus_RBfbD57HDzPKpduI8elr5qHA';
$request->amount = 5000;
$request->paymentProcessor = 'stripe';
$request->eventName = 'Purchase';
$request->invoiceId = 'in_1MtHbELkdIwH';
$request->currency = 'usd';

// Required for direct sale tracking:
$request->clickId = 'cm3w...'; // Pass the click ID from your frontend
$request->customerName = 'John Doe';
$request->customerEmail = 'john@example.com';
$request->customerAvatar = 'https://example.com/avatar.jpg';

$linkkit->track->sale($request);

Sale Event Properties

The following properties can be included when sending a sale event to LinkKit:

Property

Required

Description

customerExternalId

Yes

The unique identifier of the customer in your system. LinkKit uses this value to identify the customer and attribute future events to them.

amount

Yes

The total sale amount in cents.

paymentProcessor

No

The payment provider used to process the transaction (for example, Stripe or Shopify). Defaults to "custom".

eventName

No

The name of the sale event. Defaults to "Purchase".

invoiceId

No

The invoice or transaction ID for the sale. This can be used as an idempotency key to ensure only one sale event is recorded for a specific invoice ID.

currency

No

The currency used for the transaction. Defaults to "usd".

metadata

No

An object containing additional information or custom data related to the sale.

clickId

No

(Direct sale tracking) The unique click ID associated with the sale conversion. This value can be retrieved from the linkkit_id cookie.

customerName

No

(Direct sale tracking) The customer's name. If not provided, a random name may be generated.

customerEmail

No

(Direct sale tracking) The customer's email address.

customerAvatar

No

(Direct sale tracking) The URL of the customer's avatar or profile image.

When to Track Sales
Track sale events only after a user successfully completes a purchase or payment-related action. Make sure the event is triggered only after the backend confirms that the payment was successful.

View Your Conversions

That's it — you're all set! You can now monitor your conversion performance and track how your revenue grows through LinkKit Analytics.

LinkKit provides three different views to help you analyze and understand your conversions:

Time-Series View

Track conversion trends over time with a time-series view showing the number of:

  • Clicks – Total tracked link clicks.
  • Leads – Number of lead conversion events.
  • Sales – Number of completed sales conversions.

This view helps you monitor performance trends and understand how your conversions change over time.

Funnel Chart View

Understand your conversion journey with a funnel chart that visualizes conversion and drop-off rates across each stage of the funnel:

Clicks → Leads → Sales

This view helps you identify how users progress through each conversion stage and highlights where potential customers drop off, allowing you to optimize your funnel performance.

Real-Time Events Stream

Stay updated with live conversion activity through a real-time events stream that displays every conversion event generated across all links in your workspace.

This view provides instant access to:

  • Lead events as they are recorded.
  • Sale events as they occur.
  • Conversion activity and attribution details across your tracked links.

The real-time events stream helps you monitor ongoing campaigns, verify tracking setup, and keep track of customer conversions as they happen.