> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codeqr.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe

> Learn how to track sale conversion events with Stripe and CodeQR

<Note>
  Conversion tracking require a [Business plan](https://codeqr.iopricing)
  subscription or higher.
</Note>

When it comes to [conversion tracking](/conversions/quickstart), a `sale` event happens when a user purchases your product or service. Examples include:

* Subscribing to a paid plan
* Usage expansion (upgrading from one plan to another)
* Purchasing a product via [Stripe Payment Links](#option-1-using-stripe-payment-links)

<Frame>
  <img className="rounded-lg border border-gray-100" src="https://assets.codeqr.io/help/conversion-sale-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 sale events with Stripe as the payment processor by leveraging CodeQR's Stripe integration.

## Installing the CodeQR Stripe integration

CodeQR comes with a powerful Stripe integration that automatically listens to payment events on Stripe and track them as sales on CodeQR.

Here's how you can install the CodeQR Stripe integration:

<Steps>
  <Step title="Find CodeQR on the Stripe App Marketplace">
    Navigate to the [CodeQR Stripe Integration](https://d.to/stripe/app) on the Stripe App Marketplace.

    <Frame>
      <img src="https://mintcdn.com/codeqr/ueJ_ilTLXJXEjrH8/images/stripe/stripe-app-marketplace.png?fit=max&auto=format&n=ueJ_ilTLXJXEjrH8&q=85&s=9f4f1bfa02bf845b2cf746a348127ad1" alt="The CodeQR: Conversions Analytics page on the Stripe App Marketplace" width="1340" height="993" data-path="images/stripe/stripe-app-marketplace.png" />
    </Frame>
  </Step>

  <Step title="Install the Stripe app">
    On the top right, click on **Install app** to install the CodeQR Conversions app on your Stripe account.

    <Frame>
      <img src="https://mintcdn.com/codeqr/Dit-PkrrSHQLOViA/images/stripe/stripe-app-install.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=52b5749d6f632567fcc9d88ce96e0382" alt="The Stripe integration installation flow" width="1325" height="964" data-path="images/stripe/stripe-app-install.png" />
    </Frame>

    <Tip>
      Alternatively, you can also install the Stripe app in test mode first to test
      your end-to-end flow without involving real money.
    </Tip>

    Once the app is installed, click on **Continue to app settings** to finish the installation.

    <Frame>
      <img src="https://mintcdn.com/codeqr/Dit-PkrrSHQLOViA/images/stripe/stripe-app-install-continue.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=470625f9fff2607463ed86ca53d40751" alt="Continue to app settings" width="1264" height="855" data-path="images/stripe/stripe-app-install-continue.png" />
    </Frame>
  </Step>

  <Step title="Connect Stripe to your CodeQR project">
    In the app settings page, click on **Connect project** to connect your Stripe account with your CodeQR project.

    <Frame>
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/codeqr/images/stripe/stripe-app-connect-project.png" alt="Connect Stripe to CodeQR" />
    </Frame>

    This will redirect you to the [CodeQR OAuth flow](/integrations/quickstart), where you can select the CodeQR project you want to connect to your Stripe account.

    <Frame>
      <img src="https://mintlify.s3.us-west-1.amazonaws.com/codeqr/images/stripe/select-codeqr-project.png" alt="Select the CodeQR project you want to connect to your Stripe account" />
    </Frame>

    Once you click on **Authorize**, you will be redirected back to the CodeQR app settings page on Stripe, where you should see that the integration is now installed.

    <Frame>
      <img src="https://mintcdn.com/codeqr/Dit-PkrrSHQLOViA/images/stripe/stripe-app-installed.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=5da2b1f5fecd836a30e917f5c91f8c1d" alt="The Stripe integration is now installed" width="1057" height="558" data-path="images/stripe/stripe-app-installed.png" />
    </Frame>
  </Step>
</Steps>

Once the integration is installed, CodeQR will automatically listen to the following events on Stripe and track them as sales on CodeQR:

* `customer.created`: When a new customer is created
* `customer.updated`: When a customer is updated
* `checkout.session.completed`: When a customer completes a checkout session
* `invoice.paid`: When an invoice is paid (for tracking recurring subscriptions)
* `charge.refunded`: When a charge is refunded (for tracking refunds and updating payout commissions for [CodeQR Partners](https://codeqr.io/partners))

## Tracking sales with the CodeQR Stripe integration

Depending on your setup, there are a few ways you can track sales with the CodeQR Stripe integration.

* [Option 1: Using Stripe Payment Links](#option-1%3A-using-stripe-payment-links)
* [Option 2: Using Stripe Checkout (recommended)](#option-2%3A-using-stripe-checkout-recommended)
* [Option 3: Using Stripe Customers](#option-3%3A-using-stripe-customers)

### Option 1: Using Stripe Payment Links

<Tip>
  For this option to work, you need to [install the CodeQR Stripe
  integration](#installing-the-codeqr-stripe-integration) and [enable conversion
  tracking for your
  links](/conversions/quickstart#step-1-enable-conversion-tracking-for-your-links)
  first.
</Tip>

If you're using [Stripe Payment Links](https://docs.stripe.com/payment-links), simply add a `?codeqr_client_reference_id=1` query parameter to your Stripe Payment Link when shortening it on CodeQR.

Then, when a user clicks on the shortened link, CodeQR will automatically append the unique click ID as the `client_reference_id` [query parameter](https://docs.stripe.com/payment-links/url-parameters) to the payment link.

<Frame>
  <img src="https://assets.codeqr.iocms/conversions-payment-links.jpg" alt="Stripe payment link with CodeQR click ID" />
</Frame>

Finally, when the user completes the checkout flow, CodeQR will automatically [track the sale event](/api-reference/endpoint/track-sale) and [update the customer's `externalId`](/api-reference/endpoint/update-a-customer) with their Stripe customer ID for future reference.

Alternatively, if you have a marketing site that you're redirecting your users to first, you can do this instead:

1. [Install the @codeqr/analytics client-side SDK](/sdks/client-side/introduction), which automatically detects the `cq_id` in the URL and stores it as a first-party cookie on your site.
2. Then, retrieve and append the `cq_id` value as the `client_reference_id` parameter to the payment links on your pricing page / CTA button (prefixed with `codeqr_id_`).

   ```
   https://buy.stripe.com/xxxxxx?client_reference_id=codeqr_id_xxxxxxxxxxxxxx
   ```

<AccordionGroup>
  <Accordion title="What if I'm using Stripe Pricing Tables?">
    If you're using [Stripe Pricing Tables](https://docs.stripe.com/payments/checkout/pricing-table) – you'd want to pass the CodeQR click ID as a [`client-reference-id` attribute](https://docs.stripe.com/payments/checkout/pricing-table#handle-fulfillment-with-the-stripe-api) instead:

    <CodeGroup>
      ```html HTML theme={null}
      <body>
        <h1>We offer plans that help any business!</h1>
        <!-- Paste your embed code script here. -->
        <script async src="https://js.stripe.com/v3/pricing-table.js"></script>
        <stripe-pricing-table
          pricing-table-id="{{PRICING_TABLE_ID}}"
          publishable-key="pk_test_51ODHJvFacAXKeDpJsgWLQJSzBIDtCUFN6MoB4IIXKJDfWdFmiEO4JuvAU1A0Y2Ri4m4q1egIfwYy3s72cUBRCwXC00GQhEZuXa"
          client-reference-id="codeqr_id_xxxxxxxxxxxxxx"
        >
        </stripe-pricing-table>
      </body>
      ```

      ```jsx React theme={null}
      import * as React from "react";

      function PricingPage() {
        // Paste the stripe-pricing-table snippet in your React component
        return (
          <stripe-pricing-table
            pricing-table-id="'{{PRICING_TABLE_ID}}'"
            publishable-key="pk_test_51ODHJvFacAXKeDpJsgWLQJSzBIDtCUFN6MoB4IIXKJDfWdFmiEO4JuvAU1A0Y2Ri4m4q1egIfwYy3s72cUBRCwXC00GQhEZuXa"
            client-reference-id="codeqr_id_xxxxxxxxxxxxxx"
          ></stripe-pricing-table>
        );
      }

      export default PricingPage;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="What if I'm using Stripe's Checkout Sessions API?">
    If you're using Stripe's [Checkout Sessions API](https://docs.stripe.com/api/checkout/sessions/object) for a recurring subscription service, you might want to check out our [Stripe Checkout option](#option-2%3A-using-stripe-checkout-recommended) instead.

    If your setup doesn't involve a [lead event](/conversions/leads/introduction) and goes straight to the Stripe checkout flow (e.g. for one-time purchases), you can simply pass the CodeQR click ID (prefixed with `codeqr_id_`) as the [`client_reference_id` parameter](https://docs.stripe.com/api/checkout/sessions/object#checkout_session_object-client_reference_id) to enable conversion tracking with CodeQR.

    <CodeGroup>
      ```javascript Node.js theme={null}
      const session = await stripe.checkout.sessions.create({
        success_url: "https://example.com/success",
        line_items: [
          {
            price: "price_xxxxxxxxxxxxxxxx",
            quantity: 2,
          },
        ],
        mode: "payment",
        client_reference_id: "codeqr_id_xxxxxxxxxxxxxx",
      });
      ```

      ```python Python theme={null}
        stripe.checkout.Session.create(
          success_url="https://example.com/success",
          line_items=[{"price": "price_xxxxxxxxxxxxxxxx", "quantity": 2}],
          mode="payment",
          client_reference_id="codeqr_id_xxxxxxxxxxxxxx",
        )
      ```

      ```go Go theme={null}
        params := &stripe.CheckoutSessionParams{
          SuccessURL: stripe.String("https://example.com/success"),
          LineItems: []*stripe.CheckoutSessionLineItemParams{
            &stripe.CheckoutSessionLineItemParams{
              Price: stripe.String("price_xxxxxxxxxxxxxxxx"),
              Quantity: stripe.Int64(2),
            },
          },
          Mode: stripe.String(string(stripe.CheckoutSessionModePayment)),
          ClientReferenceID: stripe.String("codeqr_id_xxxxxxxxxxxxxx"),
        };
        result, err := session.New(params);
      ```

      ```php PHP theme={null}
        $stripe->checkout->sessions->create([
          'success_url' => 'https://example.com/success',
          'line_items' => [
            [
              'price' => 'price_xxxxxxxxxxxxxxxx',
              'quantity' => 2,
            ],
          ],
          'mode' => 'payment',
          'client_reference_id' => "codeqr_id_xxxxxxxxxxxxxx",
        ]);
      ```

      ```ruby Ruby theme={null}
        Stripe::Checkout::Session.create({
          success_url: 'https://example.com/success',
          line_items: [
            {
              price: 'price_xxxxxxxxxxxxxxxx',
              quantity: 2,
            },
          ],
          mode: 'payment',
          client_reference_id: "codeqr_id_xxxxxxxxxxxxxx",
        })
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

### Option 2: Using Stripe Checkout (recommended)

If you have a custom checkout flow that uses Stripe's `checkout.sessions.create` API, you'd want to associate the [Stripe customer object](https://docs.stripe.com/api/customers/object) with the user's unique ID in your database (which we tracked in the [lead conversion tracking step](/conversions/leads/introduction)).

This will allow CodeQR to automatically listen for purchase events from Stripe and associate them with the original click event (and by extension, the link that the user came from).

<Accordion title="How does this work?">
  Remember in the [lead conversion tracking guide](/conversions/leads/introduction), we passed the user's unique user ID along with the click event ID in the `codeqr.track.lead` call?

  ```javascript Node.js theme={null}
  await codeqr.track.lead({
    clickId,
    eventName: "Sign Up",
    externalId: user.id, // the unique user ID of the customer in your database
    customerName: user.name,
    customerEmail: user.email,
    customerAvatar: user.image,
  });
  ```

  Under the hood, CodeQR records the user as a customer and associates them with the click event that they came from.

  Then, when the user makes a purchase, CodeQR will automatically associate the checkout session details (invoice amount, currency, etc.) with the customer – and by extension, the original click event.
</Accordion>

First, you'll need to complete the following prerequisites:

1. [Install the CodeQR Stripe integration](#installing-the-codeqr-stripe-integration)
2. [Enable conversion tracking for your links](/conversions/quickstart#step-1-enable-conversion-tracking-for-your-links)
3. [Install the @codeqr/analytics client-side SDK](/sdks/client-side/introduction)
4. [Install the CodeQR server-side SDK](/conversions/quickstart#step-3-install-the-codeqr-server-side-sdk)

Then, when you [create a checkout session](https://docs.stripe.com/api/checkout/sessions/create), pass your customer's unique user ID in your database as the `codeqrCustomerId` value in the `metadata` field.

```javascript Node.js theme={null}
import { stripe } from "@/lib/stripe";

const user = {
  id: "user_123",
  email: "user@example.com",
  teamId: "team_xxxxxxxxx",
};

const priceId = "price_xxxxxxxxx";

const stripeSession = await stripe.checkout.sessions.create({
  customer_email: user.email,
  success_url: "https://app.domain.com/success",
  line_items: [{ price: priceId, quantity: 1 }],
  mode: "subscription",
  client_reference_id: user.teamId,
  metadata: {
    codeqrCustomerId: user.id, // the unique user ID of the customer in your database
  },
});
```

This way, when the customer completes their checkout session, CodeQR will automatically associate the checkout session details (invoice amount, currency, etc.) with the customer – and by extension, the original click event.

### Option 3: Using Stripe Customers

Alternatively, if you don't use Stripe's [checkout session creation flow](#option-2%3A-using-stripe-checkout-recommended), you can also pass the user ID and the click event ID (`cq_id`) in the [Stripe customer creation flow](https://docs.stripe.com/api/customers/create).

First, you'll need to complete the following prerequisites:

1. [Install the CodeQR Stripe integration](#installing-the-codeqr-stripe-integration)
2. [Enable conversion tracking for your links](/conversions/quickstart#step-1-enable-conversion-tracking-for-your-links)
3. [Install the @codeqr/analytics client-side SDK](/sdks/client-side/introduction)

Then, when you [create a Stripe customer](https://docs.stripe.com/api/customers/create), pass the user's unique user ID in your database as the `codeqrCustomerId` value in the `metadata` field.

```javascript Node.js theme={null}
import { stripe } from "@/lib/stripe";

const user = {
  id: "user_123",
  email: "user@example.com",
  teamId: "team_xxxxxxxxx",
};

const cq_id = req.headers.get("cq_id");

await stripe.customers.create({
  email: user.email,
  name: user.name,
  metadata: {
    codeqrCustomerId: user.id,
    codeqrClickId: cq_id,
  },
});
```

Alternatively, you can also pass the `codeqrCustomerId` and `codeqrClickId` values in the `metadata` field of the [Stripe customer update flow](https://docs.stripe.com/api/customers/update):

```javascript Node.js theme={null}
import { stripe } from "@/lib/stripe";

const user = {
  id: "user_123",
  email: "user@example.com",
  teamId: "team_xxxxxxxxx",
};

const cq_id = req.headers.get("cq_id");

await stripe.customers.update(user.id, {
  metadata: {
    codeqrCustomerId: user.id,
    codeqrClickId: cq_id,
  },
});
```

This way, when the customer makes a purchase, CodeQR will automatically associate the purchase details (invoice amount, currency, etc.) with the original click event.

## Currency conversion support

If you're using [Stripe's Adaptive Pricing](https://docs.stripe.com/payments/checkout/adaptive-pricing) feature, CodeQR will record the sale amount using the currency of your Stripe account:

```json checkout.session.completed theme={null}
// Stripe checkout.session.completed event payload
{
  "id": "{{EVENT_ID}}",
  "object": "event",
  "type": "checkout.session.completed",
  "data": {
    "object": {
      "id": "{{SESSION_ID}}",
      "object": "checkout.session",
      "currency": "cad",
      "amount_subtotal": 2055,
      "amount_total": 2055,
      "currency_conversion": {
        "amount_subtotal": 1500,
        "amount_total": 1500, // this is the amount that CodeQR will record
        "source_currency": "usd", // the currency of your Stripe account
        "fx_rate": "1.37"
      }
    }
  }
}
```

If you're not using Stripe Adaptive Pricing, CodeQR will record the sale amount in the default currency of your CodeQR project. This means that if you pass a different currency, it will be automatically converted to USD for reporting consistency – using the latest foreign exchange rates.

```json checkout.session.completed theme={null}
// Stripe checkout.session.completed event payload
{
  "id": "{{EVENT_ID}}",
  "object": "event",
  "type": "checkout.session.completed",
  "data": {
    "object": {
      "id": "{{SESSION_ID}}",
      "object": "checkout.session",
      "currency": "cad",
      "amount_subtotal": 2055,
      "amount_total": 2055 // this will be converted from CAD to USD
    }
  }
}
```

<Note>
  The default currency for all CodeQR projects is currently set to `USD`. We
  will add the ability to customize that in the future.
</Note>

## View conversion results

And that's it – you're all set! You can now sit back, relax, and watch your conversion revenue grow. We provide 3 different views to help you understand your conversions:

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

<Frame>
  <img src="https://mintcdn.com/codeqr/Dit-PkrrSHQLOViA/images/conversions/timeseries-chart.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=c7bac376603cd71f967f5f7b33f3cadc" 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/codeqr/Dit-PkrrSHQLOViA/images/conversions/funnel-chart.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=001b9b2dad0f759c4031d81122069a75" 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://codeqr.io/help/article/real-time-events-stream) of every single conversion event that occurs across all your links in your project.

<Frame>
  <img src="https://mintcdn.com/codeqr/Dit-PkrrSHQLOViA/images/conversions/events-table.png?fit=max&auto=format&n=Dit-PkrrSHQLOViA&q=85&s=93b55a350e472e6d7fbafa7e082bbc69" alt="The Events Stream dashboard on CodeQR" width="1600" height="900" data-path="images/conversions/events-table.png" />
</Frame>

## Example Apps

<CardGroup cols={2}>
  <Card title="CodeQR + Stripe Demo App" icon="github" href="https://github.com/codeqr-io/examples/tree/main/conversions/stripe" color="#333333">
    See the full example on GitHub.
  </Card>
</CardGroup>
