> For the complete documentation index, see [llms.txt](https://docs.humblytics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.humblytics.com/how-to-track-purchase-events/beehiiv-revenue-tracking-and-split-testing.md).

# beehiiv – Revenue Tracking & Split Testing

Track beehiiv subscription revenue in Humblytics and run split tests across your subscription plans to find out which pricing page, copy, or offer converts best.

***

## Prerequisites

### 1 · Install Humblytics via Google Tag Manager

beehiiv does not allow arbitrary script injection, so you must use Google Tag Manager to load Humblytics on your publication. Follow the [Google Tag Manager install guide](/how-to-get-started/google-tag-manager.md) first and confirm your Humblytics tag is verified before continuing.

### 2 · Connect Stripe in Humblytics

beehiiv processes paid subscriptions through Stripe. Humblytics ties revenue events back to individual visitors by matching the customer email collected on your site against the email in the Stripe charge.

1. In Humblytics, go to **Connectors** in the sidebar
2. Click **Stripe** and follow the connection flow
3. Once connected, Stripe purchases will automatically fire `revenue` events in Humblytics for any visitor whose email was captured during their session

***

## Step 1 · Add the Email Capture Tag in GTM

beehiiv collects subscriber emails on your publication's subscribe page. The snippet below intercepts that email — from the URL, from `localStorage`, or from the subscribe form — and passes it to Humblytics so the session can be matched to a Stripe purchase later.

In Google Tag Manager:

1. Click **New Tag**
2. Rename it to: **Humblytics – beehiiv Email Capture**
3. Click **Tag Configuration** → **Custom HTML**
4. Paste the script exactly as written below:

```html
<script>
(function () {
  var EMAIL_SELECTOR = "#placeholder, input[type='email'], input[placeholder*='email' i]";
  var EMAIL_STORAGE_KEYS = ["email"];

  var _latestEmail = "";
  var _hasTracked = false;

  function _cleanEmail(value) {
    if (value == null) return "";

    var str = String(value).trim();

    // Handles localStorage values like: "\"max@humblytics.com\""
    try {
      var parsed = JSON.parse(str);
      if (typeof parsed === "string") {
        str = parsed;
      }
    } catch (e) {}

    return String(str || "").trim().toLowerCase();
  }

  function _isValidEmail(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email);
  }

  function _getEmailFromUrl() {
    var email = new URLSearchParams(window.location.search).get("email");
    email = _cleanEmail(email);

    return _isValidEmail(email) ? email : "";
  }

  function _getEmailFromLocalStorage() {
    for (var i = 0; i < EMAIL_STORAGE_KEYS.length; i++) {
      var key = EMAIL_STORAGE_KEYS[i];
      var value = localStorage.getItem(key);
      var email = _cleanEmail(value);

      if (_isValidEmail(email)) {
        return email;
      }
    }

    return "";
  }

  function _getEmailFromInput() {
    var input = document.querySelector(EMAIL_SELECTOR);
    if (!input) return "";

    var email = _cleanEmail(input.value);

    return _isValidEmail(email) ? email : "";
  }

  function _getBestEmail() {
    return (
      _getEmailFromUrl() ||
      _getEmailFromLocalStorage() ||
      _getEmailFromInput() ||
      _latestEmail
    );
  }

  function _trackEmail(email) {
    var _emailToTrack = _cleanEmail(email);

    if (!_isValidEmail(_emailToTrack)) return;
    if (_hasTracked) return;

    _hasTracked = true;

    var _trackHmblEmail = function(humblytics) {
      humblytics.trackCustomer(_emailToTrack);
    };

    if (
      window.Humblytics &&
      typeof window.Humblytics.trackCustomer === "function"
    ) {
      window.Humblytics.trackCustomer(_emailToTrack);
      return;
    }

    if (typeof window.HumblyticsOnReady === "function") {
      window.HumblyticsOnReady(_trackHmblEmail);
      return;
    }

    window.HumblyticsCallbacks = window.HumblyticsCallbacks || [];
    window.HumblyticsCallbacks.push(_trackHmblEmail);
  }

  function _checkAndTrack() {
    _trackEmail(_getBestEmail());
  }

  // Track immediately if email is already in the URL.
  _checkAndTrack();

  // Watch for beehiiv saving the email to localStorage.
  var _originalSetItem = localStorage.setItem.bind(localStorage);

  localStorage.setItem = function (key, value) {
    var result = _originalSetItem(key, value);

    if (EMAIL_STORAGE_KEYS.indexOf(key) !== -1) {
      var email = _cleanEmail(value);

      if (_isValidEmail(email)) {
        _trackEmail(email);
      }
    }

    return result;
  };

  // Backup poll in case the email was already saved before this script ran.
  var _pollRef = setInterval(function () {
    if (_hasTracked) {
      clearInterval(_pollRef);
      return;
    }

    _checkAndTrack();
  }, 250);

  setTimeout(function () {
    clearInterval(_pollRef);
  }, 30000);

  // Store typed email value, but do not track until Continue / Enter.
  document.addEventListener(
    "input",
    function (event) {
      if (
        event.target &&
        event.target.matches &&
        event.target.matches(EMAIL_SELECTOR)
      ) {
        _latestEmail = _cleanEmail(event.target.value);
      }
    },
    true
  );

  document.addEventListener(
    "change",
    function (event) {
      if (
        event.target &&
        event.target.matches &&
        event.target.matches(EMAIL_SELECTOR)
      ) {
        _latestEmail = _cleanEmail(event.target.value);
      }
    },
    true
  );

  // Track when user clicks Continue.
  document.addEventListener(
    "pointerdown",
    function (event) {
      var button = event.target.closest && event.target.closest("button");
      if (!button) return;

      var text = String(button.innerText || button.textContent || "")
        .trim()
        .toLowerCase();

      if (text === "continue") {
        _checkAndTrack();
      }
    },
    true
  );

  document.addEventListener(
    "click",
    function (event) {
      var button = event.target.closest && event.target.closest("button");
      if (!button) return;

      var text = String(button.innerText || button.textContent || "")
        .trim()
        .toLowerCase();

      if (text === "continue") {
        _checkAndTrack();
      }
    },
    true
  );

  // Track if user presses Enter in the email field.
  document.addEventListener(
    "keydown",
    function (event) {
      if (
        event.key === "Enter" &&
        event.target &&
        event.target.matches &&
        event.target.matches(EMAIL_SELECTOR)
      ) {
        _latestEmail = _cleanEmail(event.target.value);
        _checkAndTrack();
      }
    },
    true
  );
})();
</script>
```

5. Click **Triggering** → select **All Pages**
6. Click **Save**
7. **Publish** your GTM container

{% hint style="info" %}
Do not modify this script. The selectors and localStorage keys are tuned specifically for beehiiv's subscribe flow. Changing them may break email capture.
{% endhint %}

***

## Step 2 · Verify Revenue Is Being Tracked

Before setting up a split test, confirm the full pipeline is working:

1. Open your beehiiv publication in a private/incognito window
2. Subscribe using a real email address
3. Complete the Stripe checkout
4. In Humblytics, go to **Attribution** — within a few minutes you should see a revenue event attributed to the session from that email

If no revenue event appears after 10 minutes, double-check that:

* Your Stripe connector is connected in Humblytics (**Connectors → Stripe**)
* The GTM container is published (not just saved)
* The Humblytics base tag fires on the subscribe page (check with GTM Preview mode)

***

## Step 3 · Create a Split Test Across Subscription Plans

With revenue tracking confirmed, you can now run a split test to determine which pricing page or subscription plan converts better.

### Set up your variants in beehiiv

Create separate subscribe pages for each plan you want to test — for example, a monthly plan page and an annual plan page. Each page needs its own distinct URL.

### Create the experiment in Humblytics

1. Go to **Experiments → New Test**
2. **Test name** – something descriptive, e.g. `Monthly vs Annual Plan Page`
3. **Pages to test** – add the URL of your primary subscribe page (the control)
4. **Variants** – add one variant per plan page URL, set each to redirect to that page's URL
5. **Traffic split** – distribute evenly across variants (e.g. 50/50)
6. **Goal** – select **Increase Revenue**
7. Enable **Non-overlapping** mode so each visitor only ever sees one variant

{% hint style="info" %}
The Revenue goal does not require a destination page URL. Humblytics counts a conversion whenever a `revenue` event fires in a visitor's session — which happens automatically when their Stripe purchase is matched to their tracked email.
{% endhint %}

8. Click **Launch Test**

***

## How It Works End-to-End

1. A visitor lands on your subscribe page — Humblytics assigns them to a variant and redirects them to the corresponding plan page
2. The visitor enters their email — the GTM tag captures it and calls `Humblytics.trackCustomer(email)`
3. The visitor completes checkout on Stripe
4. Stripe sends a webhook to Humblytics; Humblytics matches the purchase email to the tracked session
5. A `revenue` event is recorded for that session and attributed to the variant the visitor saw
6. Humblytics tallies revenue per variant and runs statistical significance analysis

You can monitor results in **Experiments → \[your test] → Results**.
