---
id: "web/web-billing/custom-metadata"
title: "Custom Metadata"
description: "RevenueCat Billing supports custom metadata that you can include when making purchases. The metadata will be propagated to webhook events and the Stripe customer object to enable its use in other systems, such as marketing or attribution tools."
permalink: "/docs/web/custom-metadata"
slug: "/web/custom-metadata"
version: "current"
original_source: "docs/web/web-billing/custom-metadata.mdx"
---

> **AI agents:** This is the Markdown version of a RevenueCat documentation page. For the complete documentation index, see [llms.txt](https://www.revenuecat.com/docs/llms.txt).

RevenueCat Billing supports custom metadata that you can include when making purchases. The metadata will be propagated to webhook events and the Stripe customer object to enable its use in other systems, such as marketing or attribution tools.

## Metadata support

If you're using the Web SDK:

- Custom metadata (key-value pairs) with `string`, `number`, `boolean` or `null` values can be included with the purchase call.
- Any [UTM parameters](https://en.wikipedia.org/wiki/UTM_parameters) present in the URL are collected automatically.

If you're using Web Purchase Links:

- [UTM parameters](https://en.wikipedia.org/wiki/UTM_parameters) that are present in the URL are collected automatically.

### Supported UTM parameters

Any of the following parameters' values will be stored if they're present in the URL where the purchase is initialized:

- `utm_source`
- `utm_medium`
- `utm_campaign`
- `utm_term`
- `utm_content`

Here's an example Web Purchase Link URL, including all UTM parameters: `https://pay.rev.cat/wlzoigfbnthvjcaw/?utm_source=google&utm_medium=ppc&utm_campaign=black_friday&utm_term=cat+food&utm_content=emailcta`

## How to send custom metadata when invoking purchase() in the Web SDK:

When invoking `purchase()`, you can provide a `metadata` object using the `PurchaseParams` interface:

```ts
    try {
        const {customerInfo} = await Purchases.getSharedInstance().purchase({
            rcPackage: pkg,
            metadata: {
                a_custom_key: "a custom value",
            },
        });
        if (Object.keys(customerInfo.entitlements.active).includes("pro")) {
            // Unlock that great "pro" content
        }
    } catch (e) {
        if (
            e instanceof PurchasesError &&
            e.errorCode == ErrorCode.UserCancelledError
        ) {
            // User cancelled the purchase process, don't do anything
        } else {
            // Handle errors
        }
    }
```

The `metadata` property accepts a key-value object with any custom data you want to send along with the purchase.
The accepted values are `string`, `number`, `boolean` and `null`.

`purchases-js` will also automatically collect any `utm` parameters in the URL and send it as metadata when invoking `purchase()`.

## How to use the collected metadata

After receiving purchases with metadata included, it can be accessed in the `INITIAL_PURCHASE` and `NON_RENEWING_PURCHASE` [webhook events](https://www.revenuecat.com/docs/integrations/webhooks/event-types-and-fields). The same values are also sent to the [Stripe Customer object metadata](https://docs.stripe.com/api/customers/object#customer_object-metadata).

You can see how to use the webhook integration to trigger automations and workflows [here](https://www.revenuecat.com/docs/integrations/webhooks).

![](https://www.revenuecat.com/docs_images/web/web-billing/metadata-in-initial-purchase-event.png)

## Opt out of the automatic collection of UTM parameters

You can opt-out of the automatic collection of UTM parameters in the Web SDK by setting the `autoCollectUTMAsMetadata` flag to `false` in the `configure` method.
Here's an example:

```ts
    const appUserId = authentication.getAppUserId(); // Replace with your own authentication system
    const httpConfig = {}; // Any setting you want to customize in purchases-js HTTP client.
    const flagsConfig = {autoCollectUTMAsMetadata: false};
    const purchases = Purchases.configure({
        apiKey: WEB_BILLING_PUBLIC_API_KEY,
        appUserId: appUserId,
        httpConfig: httpConfig,
        flags: flagsConfig,
    });
```
