Documentation

Revenue Tracking

Attribute revenue to traffic sources manually

Overview

The Stripe integration is the easiest way to track revenue. But if you use a different payment processor, have offline sales, or need custom revenue tracking, you can send revenue events directly.

Use cases:

  • PayPal, Paddle, Gumroad, or other payment processors
  • Offline or enterprise sales
  • Custom checkout flows
  • Revenue from multiple sources
  • Subscription renewals and upgrades

Client-side tracking

Track revenue directly from your frontend after a successful purchase:

// On your thank-you page or purchase confirmation
window.loamly?.event('purchase', {
  order_id: 'order_abc123',
  amount: 99.00,
  currency: 'USD'
});

Required properties

PropertyTypeDescription
amountnumberRevenue amount (in major currency units, e.g., dollars not cents)
currencystringISO 4217 currency code (USD, EUR, GBP, etc.)

Optional properties

PropertyTypeDescription
order_idstringUnique order identifier for deduplication
productstringProduct or plan name
quantitynumberNumber of items purchased
typestringTransaction type: purchase, renewal, upgrade, refund

Examples

// One-time purchase
window.loamly?.event('purchase', {
  order_id: 'ord_123',
  amount: 299,
  currency: 'USD',
  product: 'Pro Plan (Annual)'
});

// Subscription renewal
window.loamly?.event('purchase', {
  order_id: 'sub_renewal_456',
  amount: 29,
  currency: 'USD',
  product: 'Pro Plan',
  type: 'renewal'
});

// Refund (negative amount)
window.loamly?.event('purchase', {
  order_id: 'refund_789',
  amount: -99,
  currency: 'USD',
  type: 'refund'
});

Deduplication

Always include order_id to prevent duplicate revenue if the confirmation page is refreshed. Loamly will ignore duplicate order IDs.

Server-side tracking

For payments that happen entirely server-side (webhooks, API calls), use the Loamly API to send revenue events:

// After receiving a payment webhook
const response = await fetch('https://api.loamly.ai/v1/events', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LOAMLY_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    event: 'purchase',
    email: customer.email, // Required for attribution
    properties: {
      order_id: payment.id,
      amount: payment.amount / 100, // Convert from cents
      currency: payment.currency.toUpperCase(),
      product: payment.product_name
    }
  })
});

Email matching

For server-side revenue to be attributed, you must include the customer's email. Loamly matches this email to a visitor record to attribute the revenue to the original traffic source.

Match requirements

The email must have been previously captured (via form submission or identify()) before the purchase occurs. If no visitor has that email, the revenue is recorded but unattributed.

How attribution works

  1. Visitor arrives: Loamly tracks their traffic source (ChatGPT, Google, etc.)
  2. Email captured: Visitor submits a form or is identified
  3. Purchase occurs: You send a purchase event with the email
  4. Attribution: Revenue is credited to the original traffic source

Attribution window

By default, Loamly uses a 30-day attribution window. A visitor who first arrived from Perplexity and converts within 30 days has that revenue attributed to Perplexity.

Multi-touch attribution

If a visitor has multiple touchpoints, Loamly uses first-touch attribution by default. The first traffic source gets credit for the conversion.

Best practices

  • Always use order_id. This prevents duplicate revenue from page refreshes or retry logic.
  • Track refunds. Send refunds as negative amounts to keep revenue accurate.
  • Use consistent currency. Convert to a single currency if possible, or let Loamly handle conversion.
  • Include product details. This helps segment revenue by product in your reports.
  • Test thoroughly. Verify revenue appears correctly in your dashboard before going live.

Prefer Stripe?

If you use Stripe, the native Stripe integration handles all of this automatically. No code required beyond connecting your account.