DEV Community

Krishna
Krishna

Posted on

Building a UTM Attribution Engine with Supabase Edge Functions (Open Source)

One of the hardest problems in marketing automation is attribution — knowing which ad drove which payment.

I built an open-source UTM attribution engine using Supabase Edge Functions. Here is how it works.

The Problem

A coach runs Meta ads → visitor lands on landing page → eventually pays on Razorpay. But how do you connect the ad click to the payment?

The Solution: 3 Edge Functions

1. track-visitor

When someone lands on your page, a JavaScript snippet captures UTM parameters and sends them to a Supabase Edge Function:

// Captures utm_source, utm_medium, utm_campaign, utm_content
fetch(TRACK_URL, {
  method: "POST",
  body: JSON.stringify({
    visitor_id: visitorId,
    utm_source: getCookie("utm_source"),
    utm_campaign: getCookie("utm_campaign"),
    page_url: window.location.href
  })
});
Enter fullscreen mode Exit fullscreen mode

The Edge Function also detects the visitor city using Cloudflare headers — free, no API key needed.

2. razorpay-webhook

When a payment is captured, Razorpay sends a webhook. Our Edge Function:

  1. Validates the webhook signature
  2. Extracts email, phone, amount
  3. Matches the payment to the most recent UTM visitor (within 24 hours)
  4. Updates the contact record with attribution data

3. The Matching Algorithm

Payment comes in (email: user@example.com)
→ Query utm_visitors table for recent unmatched visitors
→ Match by timing (closest visitor to payment time)
→ Copy UTM data to automation_contacts
→ Now we know: this payment came from Facebook, Campaign X, Creative Y
Enter fullscreen mode Exit fullscreen mode

The Result

You can see in your dashboard: Ad Creative A drove 5 payments totaling $500. Ad Creative B drove 1 payment of $100. Scale Creative A, kill Creative B.

Get the Code

This is part of Claude Coach Kit — a free, open-source marketing automation toolkit.

⭐ GitHub: github.com/krishna-build/claude-coach-kit

MIT licensed. Built with Claude.

Top comments (0)