Revenue

Attach amounts to any event. Ask your agent which channel made the most money, what a signup from Hacker News is worth, or how ARR from the spring campaign is trending.

The Money type

Clamp has one special property shape: Money. An amount and an ISO 4217 currency code. Send it on any event and Clamp stores it as a first-class numeric column, not a string.

Shape
type Money = {
  amount: number           // in major units (29.00, not 2900)
  currency: string         // ISO 4217, e.g. "USD", "EUR", "JPY"
}

Tracking revenue

Any event property whose value is a Money object is treated as revenue. You can attach more than one (total, tax, mrr) and query each independently.

Browser
import { track } from "@clamp-sh/analytics"

track("checkout_completed", {
  plan: "pro",
  interval: "annual",
  total: { amount: 348.00, currency: "USD" },
  tax:   { amount:  52.20, currency: "USD" },
})
Server
import { track } from "@clamp-sh/analytics/server"

await track("subscription_created", {
  anonymousId: "anon_abc123",
  properties: {
    plan: "pro",
    mrr: { amount: 29.00, currency: "USD" },
  },
})

The server SDK is where most production revenue tracking lives. Browser calls are fine for prototyping, but authoritative numbers (after a Stripe webhook fires, after a refund, after proration) belong on the server. See Server-side.

Data attributes

With the dataAttributes extension enabled, mark any element with data-clamp-money-key="amount currency" and Clamp parses it into a Money property when the event fires.

Pricing button
<button
  data-clamp-event="checkout_clicked"
  data-clamp-plan="pro"
  data-clamp-money-price="29.00 USD"
>
  Start on Pro — $29/mo
</button>

// Fires: track("checkout_clicked", {
//   plan: "pro",
//   price: { amount: 29, currency: "USD" }
// })

Useful for pricing pages, CMS content, and anywhere the amounts live in markup already. See Data attributes for the full syntax.

Querying revenue

The get_revenue MCP tool aggregates any Money property on any event. Group by channel, country, UTM source, or custom property.

MCP examples
"How much revenue did we make this month?"
→ get_revenue({ event: "checkout_completed", property: "total", period: "30d" })

"Break down MRR by plan"
→ get_revenue({
    event: "subscription_created",
    property: "mrr",
    group_by: "plan"
  })

"Which channel drove the most revenue?"
→ get_revenue({
    event: "checkout_completed",
    property: "total",
    group_by: "channel"
  })

"Revenue from the spring-launch campaign"
→ get_revenue({
    event: "checkout_completed",
    property: "total",
    utm_campaign: "spring-launch"
  })

Currency handling

Clamp does not convert currencies. Each Money value is stored with its original currency and aggregated per currency in the response. If you charge in mixed currencies, get_revenue returns a breakdown like { USD: 12400, EUR: 3200 }. Convert downstream with whatever rate your finance team uses.

Refunds and negatives

Negative amounts are allowed. Track refunds as their own event with a negative total, or flip the sign on the original event’s Money property when you reprocess it server-side.

await track("refund_issued", {
  anonymousId,
  properties: {
    original_event_id: "evt_xxx",
    total: { amount: -29.00, currency: "USD" },
  },
})

get_revenue sums everything, so refunds net out automatically when grouped alongside the original events.