ShubhamVankalas/adledger

Self-hosted ad attribution, revenue ledger and CRM. See which ad actually made you money. Free to self-host, source available (FSL-1.1).

TypeScript

0

278 commits

updated Sep 29, 2026

See the code

See what people are saying

SourceMessageScoreDate

I made a free ad attribution tool and CRM you can run on your own server (r/SideProject)

Been building this with Claude. It's called **AdLedger**. It connects your ad spend (Meta, Google, etc.), your website visits, and your Stripe payments and shows you which ad actually made you money. Also has a small CRM, live view, PDF reports, and an MCP server so you can ask Claude about your…

1

Sep 29, 2026

README

AdLedger: know which ad actually made you money. Self-hosted ad attribution, revenue ledger and CRM that runs on your own server. Source available under FSL-1.1.

Every sale gets a receipt.

See which ad actually made you money, what that customer really cost, and prove it.
Self-hosted ad attribution, revenue ledger and CRM.
Free to self-host. Source available (FSL-1.1). Your server, your data.

License: FSL-1.1 CI Docker image GitHub stars Self-hosted PRs welcome

Website · Install · Docs · Features · Developers · Roadmap

AdLedger in motion: the dashboard assembles in 3D and each module lifts out


What is AdLedger?

AdLedger joins ad spend (Meta, Google and 7 more networks), website events from a 2.4 KB pixel, leads and real payments (Stripe and 12 more) into one ledger, so every number is computed in SQL, split to the cent and shown per campaign, ad set and ad. One container plus PostgreSQL, on a server you control.

Not sure yet? Take the 3D product tour, or run the demo below with 90 days of sample data.

What you get

Ad Receipts: every sale gets a receipt. See which ads earned each payment, what that customer cost and when they paid it back.Live: watch it happen. Visitors, ad clicks, leads and payments as they land.
Attribution: first, last and linear touch with cent-exact credit splits and real customer journeys.Profit Ledger: profit after ads, POAS, break-even ROAS and refund rates.
CRM and Pipeline: contacts, tasks, a drag-and-drop pipeline and ad cost per stage.Reports, AI and MCP: 11 PDF reports, 12 AI document templates and an MCP server.
Developers: API keys, signed webhooks, an API reference and recipes.Security built in: two-factor sign-in, custom roles, a hash-chained audit log, masked emails and consent modes.

Free to self-host, with the source on GitHub. No per-seat or revenue-share pricing. Unlimited users, workspaces and client logins.
Your data never leaves your server. No telemetry, no licence check, no phone-home.

Install in 60 seconds

You need Docker. This starts AdLedger with 90 days of demo data:

git clone https://github.com/ShubhamVankalas/adledger.git && cd adledger
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=adledger-demo-123 DEMO_DATA=true docker compose up -d

Open http://localhost:3000 and sign in. The demo runs on mock connectors that speak each platform's real API format (Meta, Google, TikTok, LinkedIn, Microsoft, Stripe). Or run plain docker compose up -d, create your account and choose Explore with demo data.

Docker Desktop (Windows or macOS)
  1. Install Docker Desktop and start it.
  2. Clone the repo, then in PowerShell run:
$env:ADMIN_EMAIL="admin@example.com"; $env:ADMIN_PASSWORD="adledger-demo-123"; $env:DEMO_DATA="true"
docker compose up -d
  1. Open http://localhost:3000. Leave out the three variables to start empty and create your own account.
A server with your own domain (automatic HTTPS, random secrets generated)

Point an A record at the server, open ports 80 and 443, then:

curl -fsSL https://raw.githubusercontent.com/ShubhamVankalas/adledger/main/install.sh | DOMAIN=ads.yourcompany.com sh

The script installs nothing but AdLedger: it downloads docker-compose.yml, writes a .env with generated secrets, and starts the app, PostgreSQL 16 and Caddy. Re-run it to upgrade.

Render, Railway, Coolify and friends
WhereHow
RenderDeploy to Render uses render.yaml: web service, managed PostgreSQL 16 and a generated APP_SECRET.
RailwayDeploy from your fork (uses the Dockerfile and railway.json), add PostgreSQL, set DATABASE_URL=${{Postgres.DATABASE_URL}}.
Coolify, Dokploy, CapRover, PortainerDeploy docker-compose.yml as-is.
Single container, no PostgreSQLdocker run -d -p 3000:3000 -v adledger:/data ghcr.io/shubhamvankalas/adledger (embedded database; fine for trials, use PostgreSQL for production).
From source, no Docker (Node 20+ and pnpm)
pnpm install && pnpm dev     # http://localhost:3000, embedded database in ./.data

Upgrade with docker compose pull && docker compose up -d. Backups, HTTPS and every setting: docs/SELF_HOSTING.md.

Features

A dashboard you arrange yourself

Overview: a briefing line naming the most profitable campaign, KPI tiles for revenue, ad spend, ROAS, MER, customers and unattributed share, and a revenue chart against the previous period

The Overview is a widget board. Press Customize (or E) to drag, resize and group widgets and pin up to six KPI tiles. Start from a preset (Minimal, E-commerce, Lead gen, Agency) or set the workspace default for the whole team.

  • A briefing line names what mattered, built from SQL numbers, not a language model.
  • KPI tiles with change vs the previous period, sparklines and a metric explorer.
  • Date presets, compare, platform filter and attribution model live in the URL, so every view is a link.

Live

Visitors on your site right now, today vs the same time yesterday, and a real-time feed of ad clicks, visits, leads, payments and refunds (server-sent events, no extra service).

  • The Live pill in every page header shows visitors and today's revenue, one click from Live.
  • Streamer mode (S) hides names. Sale alerts (A) pop a toast for every payment.
Live view with visitors on the site now, revenue, spend, leads and customers today vs yesterday, and a real-time activity feed

Performance and attribution

Performance table with spend, clicks, leads, CPL, customers, CAC, platform gap, revenue and ROAS per campaign

Campaigns, ad sets and ads with column presets, NC-ROAS, a platform gap column (what the platform reports next to what AdLedger verified), a quadrant that sorts campaigns into scale, test, fix and kill, and saved views with a peek into the people a campaign brought in.

First touch, last touch and linear, switchable anywhere, with exact integer-cent splits that always add up to the payment. Paths shows the journeys customers took, Time to convert shows whether your attribution window is long enough, and unattributed revenue is always shown, never hidden.

Top customer journeys as channel chips with revenue, median days and touches, beside a visit-to-revenue funnel
Cohort heatmap by first-payment month with retention, CAC and a dot where each cohort paid back its acquisition cost

Customers: LTV and cohorts. Lifetime value by acquiring channel, LTV:CAC and a cohort heatmap by first-payment month (retention, cumulative LTV or revenue), with a dot where each cohort paid back its CAC. Renewals are credited to the journey that first acquired the customer.

Signature money features

Ad Receipts. Every payment shows which ads earned it, what that customer cost in ad spend and when they paid it back. Customer costs plus unallocated equal total spend, to the cent.

Receipts: where the ad spend went, then each payment with the ad that mostly earned it, the cost to acquire and a payback tag

Profit Ledger. Enter cost of goods, payment fees and shipping once. Get contribution, profit after ads, POAS, break-even ROAS and a P&L waterfall, plus which ads bring buyers who refund.

Profit ledger with net revenue, contribution, profit after ads, POAS and a profit and loss waterfall

Truth Gap. "Meta says its ads made you this much; real payments from people who clicked them were that much." Claimed vs verified conversions and value per platform and campaign.

Too-early guardrails. Median and p80 days from first click to first payment, a "too early to judge" tag on young campaigns, and pause drafts you download as a Meta or Google Ads Editor file. AdLedger never writes to your ad accounts.

A CRM that knows what each lead cost

Contacts table with view tabs, status, first touch, revenue and owner
Contacts. Saved views, filters, groups, bulk actions with undo, fast at 10k+ contacts.
Contact record with highlights, properties and a unified activity timeline of ad clicks, page views, forms and payments
Record page. Ad clicks, visits, forms and payments on one timeline, plus notes, tasks and attribution.
Pipeline kanban with New lead, Qualified, Call booked and Proposal columns, weighted value and rotting counts
Pipeline. Drag by mouse, touch or keyboard. Payments move contacts to Won automatically.

Also: My tasks, CSV import with a preview before anything is written, and duplicate review and merge with re-attribution.

Reports, PDFs and AI documents

Report library with executive summary, weekly performance, attribution model comparison, LTV and cohorts, and wasted spend reports

Eleven print-ready PDF reports: executive summary, weekly performance, attribution model comparison, LTV and cohorts, wasted spend, channel mix, lead source quality, creative and ad leaderboard, funnel and time to convert, pipeline and CRM activity and profit and refunds.

Your logo on the masthead, a methodology appendix, a "Prepared for" watermark and a fingerprint on every page that anyone can check at /verify. Download, call the API, or schedule weekly or monthly emails. Rendered in-process: no headless browser, no extra container. docs/REPORTS.md

AI document generator. Pick one of 12 prompt templates (monthly client report, board update, post-mortem, budget memo, Meta vs Google, lead quality audit, stand-up, case study, creative brief, quarter review, funnel leaks, refunds) or write your own. Your model writes the words; AdLedger draws every KPI, table and chart from SQL, removes any sentence with a number that is not in the data, and lays it out as a branded, fingerprinted PDF with an in-app preview.

Insights and Ask AI

Action cards (move budget, room to grow, revenue drop, CAC up) where every figure links to its source row, a weekly report marked All numbers verified, and Ask: plain-language questions answered from read-only SQL tools, with the table each answer came from. Any number a model invents is flagged. Works with no model at all, a local model (Ollama, LM Studio) or OpenAI, Anthropic, Gemini, OpenRouter, DeepSeek and any OpenAI-compatible endpoint.

Insights action cards: move budget, room to grow and a revenue drop, with every figure linked to its source

Alerts, sharing, goals and speed

  • Alert rules on CAC, CPL, ROAS, spend, revenue or leads with cooldowns, plus optional anomaly detection.
  • Notifications by email, Slack, Discord, Microsoft Teams, SMS (Twilio) or signed webhook.
  • Share links: read-only aggregate dashboards with locked filters, an expiry, a view count and one-click revoke. Contact details are never shared.
  • Targets and goals with pacing and projection to period end.
  • Ctrl K / ⌘K finds any page, contact or campaign; G then a letter jumps between pages; ? lists shortcuts.
  • Product tour: a 2-minute spotlight tour on first sign-in that shows each person only what their role can open.
  • Your colours: 20 solid themes and 10 gradients for the whole organization, all passing WCAG AA. Profit and loss stay green and red.
  • Custom roles with per-page and per-action permissions, next to five built-in roles (owner, admin, analyst, viewer, client).
  • Installable on your phone (PWA) with a bottom tab bar, and a dark mode that follows your system.

Developers: API, webhooks, recipes

Developers area with a quickstart, API keys, webhooks and delivery health

A dedicated Developers area (owners and admins by default) for wiring AdLedger into your own tools:

  • API keys with scopes (reports:read, mcp, contacts:read, contacts:pii, ingest:write), optional expiry, stored hashed.
  • Signed outbound webhooks for lead.created, contact.created, contact.updated, payment.succeeded and payment.refunded: HMAC-SHA256 signatures, retries with backoff for about two days, a 30-day delivery log with redeliver, Send test event, masked emails unless you opt in, private URLs blocked. docs/WEBHOOKS.md
  • API reference generated from the OpenAPI 3.1 spec, with curl, JavaScript and Python examples. docs/API.md
  • Recipes you can copy: SMS a new lead in seconds (Twilio), send a Cal.com booking link, shout out payments in Slack, connect Zapier, Make or n8n, or append rows to Google Sheets.
# Pull leads with a read key
curl -H "Authorization: Bearer al_..." https://your-adledger/api/v1/leads

MCP server for AI assistants

Ask Claude, Cursor or any MCP client "which ads made money last month?" against your own ledger. Create a key in Developers → API keys, then:

claude mcp add --transport http adledger https://your-adledger/api/mcp --header "Authorization: Bearer al_..."
14 read-only tools

get_overview, get_performance, find_wasted_spend, compare_periods, get_platform_breakdown, get_timeseries, search_campaigns, contact_stage_funnel, list_contacts, get_contact_journey, get_ad_receipt, get_latest_insights, get_sync_status, list_integrations.

Every tool is annotated read-only and a test proves none of them changes data. Emails are masked. Setup for Claude Desktop and Cursor: docs/MCP.md.

Integrations

Connected from Settings → Integrations, with step-by-step instructions on each card and a mock mode for every connector.

Ad platformsMeta Ads, Google Ads, Microsoft Ads, TikTok Ads, LinkedIn Ads, Pinterest Ads, Snapchat Ads, Reddit Ads, X Ads. Anything else by CSV or the Spend API.
Payments and storesStripe (paste one key, the webhook is created for you), Shopify, WooCommerce, Paddle, Lemon Squeezy, Razorpay, PayPal, Chargebee, Recurly, Gumroad, Cashfree, Instamojo, PhonePe. Anything else by CSV or the Conversions API.
CRMsWon deals from HubSpot and Pipedrive.
Lead formsAny form with data-adledger-lead, Typeform, Tally, Webflow, Zapier or Make webhooks, native Meta Lead Ads, Google Ads lead forms, TikTok Lead Generation and WhatsApp click-to-chat.
Your websiteOne <script> tag (2.4 KB gzipped), a WordPress/WooCommerce plugin, a Shopify custom pixel, a GTM template and guides for Webflow, Wix, Squarespace, Framer and Next.js.
Back to the ad platforms (beta)Consent-aware conversion upload to the Meta Conversions API and Google Ads, hashed identifiers only.
NotificationsEmail, Slack, Discord, Microsoft Teams, SMS (Twilio), signed webhook.

Connectors other than Meta, Google Ads and Stripe are in beta: tested against real-format fixtures, not yet verified on live accounts. Details: docs/CONNECTORS.md.

Screenshots

OverviewRevenue and ROAS by attribution model
OverviewRevenue and ROAS under first touch, last touch and linear per campaign, with journey starters and closers
Time to convertTime to money and pause drafts
Lag histograms from first touch to lead and payment, with a recommended attribution windowMedian days from first click to payment, pause drafts for Meta and Google Ads Editor, and payback lag by campaign
Ask your numbersSecurity policy and posture checklist
Ask panel with suggested questions answered from the ledgerSecurity policy checklist: encryption key storage, HTTPS, two-factor coverage, session limits and audit verification
30+ integrationsGuided setup checklist
Integrations catalogSetup checklist that adapts to your website builder, payment tools and ad platforms
More: tracking, team, alerts, audit log, two-factor sign-in, notifications, report verification
Tracking snippet and consent modesMembers and roles
Tracking settingsMembers and roles
Alert rules and anomaly detectionHash-chained audit log
Alerts settingsAudit log with export and verify chain
Two-factor sign-in and devicesNotification channels
Account security with two-factor sign-in and signed-in devicesNotification channels
Verify a PDF report
Public verify page for report fingerprints

On your phone: installable as an app, with a floating tab bar and a one-tap filter sheet.

Overview on a phone Live on a phone Performance on a phone Integrations on a phone

Security and compliance

GDPR-ready tooling SOC 2-aligned controls Free two-factor sign-in Hash-chained audit log AES-256-GCM for stored credentials Non-root container image CodeQL and image scanning

AdLedger is self-hosted software, so it holds no certification and makes no compliance claim on your behalf. It ships GDPR-ready tooling and SOC 2-aligned controls to help you meet GDPR, UK GDPR, CCPA/CPRA and India's DPDP; when you self-host, you are the data controller. SOC 2 and ISO 27001 assess the organisation that runs a service, so they apply to you, not to the project. What AdLedger gives that organisation is controls and evidence that make those audits easier.

FrameworkWhat AdLedger providesGuide
GDPR / UK GDPRConsent modes, export, erasure, retention, hashing, masking, audit trailArt. by Art.
CCPA / CPRAGlobal Privacy Control, consent-aware uploads, access and deleteRequirements
ePrivacy / PECRConsent-required and cookieless pixel modes, banner snippetsCookies
SOC 2Controls that map to CC6 (access), CC7 (monitoring), CC8 (change), C1 and P criteriaMapping
ISO/IEC 27001:2022Supports the relevant Annex A controlsMapping
OWASP Top 10, ASVS, CIS DockerSelf-assessed against the public lists; no formal verificationTables

Not covered: HIPAA and health data, and children's data. Card data never touches AdLedger (your payment provider holds it). See what is not covered and the go-live checklist.

Every control, by area
AreaControls
Sign-inFree two-factor sign-in (TOTP + recovery codes) that owners can require org-wide, with a documented break-glass for a locked-out owner. scrypt passwords under a NIST SP 800-63B-4 policy.
SessionsHashed tokens, idle timeout and maximum lifetime, a device list with sign out one or everywhere, new-device emails.
AccessFive built-in roles plus custom roles with per-page and per-action permissions. Contact emails masked by role, with every reveal audited. Separate permissions for aggregate CSVs, contact exports and PDFs.
PIIRaw emails only in the contacts table; SHA-256 hashes everywhere else. IPs truncated. Stored payloads redacted.
Secrets and keysConnector credentials and 2FA secrets encrypted with AES-256-GCM. API keys stored hashed, with scopes and optional expiry.
AuditTamper-evident, hash-chained audit log with Verify, filters and CSV export. Security alerts for new keys, webhooks, role changes, 2FA resets, bulk exports and new-device sign-ins.
ConsentPixel consent modes (opt-out, consent required, cookieless) and Global Privacy Control. Conversion uploads carry consent signals, and people who said no are never uploaded.
Data rightsPer-contact export and erasure (UI and API), full workspace export, raw-event retention.
Leak deterrenceWatermarked, fingerprinted PDFs verifiable at /verify, an export log, aggregate-only share links.
Web and supply chainCSP and security headers, SSRF guards, signed webhooks. CodeQL, dependency review, pnpm audit, Trivy image scans, Dependabot, SBOM and provenance on release images.
Disclosure/.well-known/security.txt on every install and private vulnerability reporting (SECURITY.md).

Read the Trust and security page for the mechanisms and the hardening checklist, and the Compliance guide for the framework mappings and the statements that are safe to make about your install.

Architecture

One Next.js app and PostgreSQL. The dashboard, REST API, pixel collector, webhooks, MCP server, live stream, PDF rendering and background jobs all run in a single container.

 your website ──al.js──▶ /api/v1/collect ─────┐
 forms, CRMs ──webhook─▶ /api/v1/webhooks ────┤
 Stripe, stores ─webhook▶ /api/v1/webhooks ───┼──▶  AdLedger (Next.js)  ──▶  PostgreSQL 16
 ad platforms ◀── scheduled sync / uploads ───┤        ▲ dashboard, /share, /verify
 Claude, Cursor ──MCP──▶ /api/mcp ────────────┘        └──▶ signed webhooks out

Stack: Next.js 16 · React 19 · TypeScript · PostgreSQL 16 (Drizzle ORM, embedded PGlite for trials) · Tailwind CSS v4 + shadcn/ui · Recharts · react-pdf · Vercel AI SDK · MCP SDK · vitest · Playwright. Details and design decisions: docs/ARCHITECTURE.md.

Documentation

DocWhat's in it
FeaturesEvery page and setting, grouped
Self-hostingInstall options, HTTPS, upgrades, backups, configuration
ConnectorsSetting up each integration, UTM templates, mock mode
Site-builder guidesWebflow, Wix, Squarespace, Framer, Next.js, GTM, Shopify, WordPress
PixelThe tracking script, its API and consent
ReportsPDF reports, AI documents, schedules, watermarks and verification
API · Webhooks · MCPREST API, signed outbound webhooks and recipes, AI assistant tools
Trust and securityControls, privacy, hardening checklist, disclosure
ComplianceGDPR, CCPA, SOC 2, ISO 27001, OWASP and CIS mappings, go-live checklist, safe claims
FAQData, accuracy, iOS, cost, 2FA lockout, compliance questions
Architecture · Product · RoadmapHow it's built, who it's for, what's next

Roadmap

What is shipped and what is next lives in docs/ROADMAP.md. Ideas and votes are welcome in issues.

Contributing

pnpm install
pnpm dev                   # http://localhost:3000, embedded database, no Docker needed
pnpm test                  # vitest on an embedded Postgres, every connector mocked
pnpm lint && pnpm typecheck
pnpm build && pnpm e2e     # Playwright browser tests with axe accessibility checks

Bug reports, connectors, report kinds and docs fixes are welcome. Start with CONTRIBUTING.md and the roadmap. Found a security issue? See SECURITY.md.

License

AdLedger is source available under the Functional Source License, FSL-1.1-ALv2, a "Fair Source" licence. It is not an OSI-approved open source licence.

  • What you can do: use it and self-host it for free, including for a business or an agency running its own ads, read and modify the code, and contribute changes back.
  • What you can't do: sell it, sell a modified version, or offer it (or something substantially similar built from it) as a competing product or hosted service.
  • After two years: each version automatically converts to the permissive Apache-2.0 licence, counted from the date that version was released.

Contributions are accepted under the same licence (see CONTRIBUTING.md). The name and logo are covered by TRADEMARKS.md. The WordPress plugin in integrations/wordpress is a separate work licensed GPL-2.0-or-later, as WordPress.org requires.


Shubham Vankalas

Built by Shubham Vankalas, as a free-to-self-host tool for founders who want to know which ad paid off.

If AdLedger shows you which ad made you money, give it a star. It helps other founders find it.

Star history chart for AdLedger

Website · Issues · Contribute

ad-attribution
analytics
conversion-tracking
crm
docker
fair-source
google-ads
marketing-attribution
mcp
meta-ads
nextjs
postgresql
revenue-tracking
roas
self-hosted
source-available
stripe

ShubhamVankalas/adledger

Self-hosted ad attribution, revenue ledger and CRM. See which ad actually made you money. Free to self-host, source available (FSL-1.1).

TypeScript

0

278 commits

updated Sep 29, 2026

See the code

See what people are saying

SourceMessageScoreDate

I made a free ad attribution tool and CRM you can run on your own server (r/SideProject)

Been building this with Claude. It's called **AdLedger**. It connects your ad spend (Meta, Google, etc.), your website visits, and your Stripe payments and shows you which ad actually made you money. Also has a small CRM, live view, PDF reports, and an MCP server so you can ask Claude about your…

1

Sep 29, 2026

README

AdLedger: know which ad actually made you money. Self-hosted ad attribution, revenue ledger and CRM that runs on your own server. Source available under FSL-1.1.

Every sale gets a receipt.

See which ad actually made you money, what that customer really cost, and prove it.
Self-hosted ad attribution, revenue ledger and CRM.
Free to self-host. Source available (FSL-1.1). Your server, your data.

License: FSL-1.1 CI Docker image GitHub stars Self-hosted PRs welcome

Website · Install · Docs · Features · Developers · Roadmap

AdLedger in motion: the dashboard assembles in 3D and each module lifts out


What is AdLedger?

AdLedger joins ad spend (Meta, Google and 7 more networks), website events from a 2.4 KB pixel, leads and real payments (Stripe and 12 more) into one ledger, so every number is computed in SQL, split to the cent and shown per campaign, ad set and ad. One container plus PostgreSQL, on a server you control.

Not sure yet? Take the 3D product tour, or run the demo below with 90 days of sample data.

What you get

Ad Receipts: every sale gets a receipt. See which ads earned each payment, what that customer cost and when they paid it back.Live: watch it happen. Visitors, ad clicks, leads and payments as they land.
Attribution: first, last and linear touch with cent-exact credit splits and real customer journeys.Profit Ledger: profit after ads, POAS, break-even ROAS and refund rates.
CRM and Pipeline: contacts, tasks, a drag-and-drop pipeline and ad cost per stage.Reports, AI and MCP: 11 PDF reports, 12 AI document templates and an MCP server.
Developers: API keys, signed webhooks, an API reference and recipes.Security built in: two-factor sign-in, custom roles, a hash-chained audit log, masked emails and consent modes.

Free to self-host, with the source on GitHub. No per-seat or revenue-share pricing. Unlimited users, workspaces and client logins.
Your data never leaves your server. No telemetry, no licence check, no phone-home.

Install in 60 seconds

You need Docker. This starts AdLedger with 90 days of demo data:

git clone https://github.com/ShubhamVankalas/adledger.git && cd adledger
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=adledger-demo-123 DEMO_DATA=true docker compose up -d

Open http://localhost:3000 and sign in. The demo runs on mock connectors that speak each platform's real API format (Meta, Google, TikTok, LinkedIn, Microsoft, Stripe). Or run plain docker compose up -d, create your account and choose Explore with demo data.

Docker Desktop (Windows or macOS)
  1. Install Docker Desktop and start it.
  2. Clone the repo, then in PowerShell run:
$env:ADMIN_EMAIL="admin@example.com"; $env:ADMIN_PASSWORD="adledger-demo-123"; $env:DEMO_DATA="true"
docker compose up -d
  1. Open http://localhost:3000. Leave out the three variables to start empty and create your own account.
A server with your own domain (automatic HTTPS, random secrets generated)

Point an A record at the server, open ports 80 and 443, then:

curl -fsSL https://raw.githubusercontent.com/ShubhamVankalas/adledger/main/install.sh | DOMAIN=ads.yourcompany.com sh

The script installs nothing but AdLedger: it downloads docker-compose.yml, writes a .env with generated secrets, and starts the app, PostgreSQL 16 and Caddy. Re-run it to upgrade.

Render, Railway, Coolify and friends
WhereHow
RenderDeploy to Render uses render.yaml: web service, managed PostgreSQL 16 and a generated APP_SECRET.
RailwayDeploy from your fork (uses the Dockerfile and railway.json), add PostgreSQL, set DATABASE_URL=${{Postgres.DATABASE_URL}}.
Coolify, Dokploy, CapRover, PortainerDeploy docker-compose.yml as-is.
Single container, no PostgreSQLdocker run -d -p 3000:3000 -v adledger:/data ghcr.io/shubhamvankalas/adledger (embedded database; fine for trials, use PostgreSQL for production).
From source, no Docker (Node 20+ and pnpm)
pnpm install && pnpm dev     # http://localhost:3000, embedded database in ./.data

Upgrade with docker compose pull && docker compose up -d. Backups, HTTPS and every setting: docs/SELF_HOSTING.md.

Features

A dashboard you arrange yourself

Overview: a briefing line naming the most profitable campaign, KPI tiles for revenue, ad spend, ROAS, MER, customers and unattributed share, and a revenue chart against the previous period

The Overview is a widget board. Press Customize (or E) to drag, resize and group widgets and pin up to six KPI tiles. Start from a preset (Minimal, E-commerce, Lead gen, Agency) or set the workspace default for the whole team.

  • A briefing line names what mattered, built from SQL numbers, not a language model.
  • KPI tiles with change vs the previous period, sparklines and a metric explorer.
  • Date presets, compare, platform filter and attribution model live in the URL, so every view is a link.

Live

Visitors on your site right now, today vs the same time yesterday, and a real-time feed of ad clicks, visits, leads, payments and refunds (server-sent events, no extra service).

  • The Live pill in every page header shows visitors and today's revenue, one click from Live.
  • Streamer mode (S) hides names. Sale alerts (A) pop a toast for every payment.
Live view with visitors on the site now, revenue, spend, leads and customers today vs yesterday, and a real-time activity feed

Performance and attribution

Performance table with spend, clicks, leads, CPL, customers, CAC, platform gap, revenue and ROAS per campaign

Campaigns, ad sets and ads with column presets, NC-ROAS, a platform gap column (what the platform reports next to what AdLedger verified), a quadrant that sorts campaigns into scale, test, fix and kill, and saved views with a peek into the people a campaign brought in.

First touch, last touch and linear, switchable anywhere, with exact integer-cent splits that always add up to the payment. Paths shows the journeys customers took, Time to convert shows whether your attribution window is long enough, and unattributed revenue is always shown, never hidden.

Top customer journeys as channel chips with revenue, median days and touches, beside a visit-to-revenue funnel
Cohort heatmap by first-payment month with retention, CAC and a dot where each cohort paid back its acquisition cost

Customers: LTV and cohorts. Lifetime value by acquiring channel, LTV:CAC and a cohort heatmap by first-payment month (retention, cumulative LTV or revenue), with a dot where each cohort paid back its CAC. Renewals are credited to the journey that first acquired the customer.

Signature money features

Ad Receipts. Every payment shows which ads earned it, what that customer cost in ad spend and when they paid it back. Customer costs plus unallocated equal total spend, to the cent.

Receipts: where the ad spend went, then each payment with the ad that mostly earned it, the cost to acquire and a payback tag

Profit Ledger. Enter cost of goods, payment fees and shipping once. Get contribution, profit after ads, POAS, break-even ROAS and a P&L waterfall, plus which ads bring buyers who refund.

Profit ledger with net revenue, contribution, profit after ads, POAS and a profit and loss waterfall

Truth Gap. "Meta says its ads made you this much; real payments from people who clicked them were that much." Claimed vs verified conversions and value per platform and campaign.

Too-early guardrails. Median and p80 days from first click to first payment, a "too early to judge" tag on young campaigns, and pause drafts you download as a Meta or Google Ads Editor file. AdLedger never writes to your ad accounts.

A CRM that knows what each lead cost

Contacts table with view tabs, status, first touch, revenue and owner
Contacts. Saved views, filters, groups, bulk actions with undo, fast at 10k+ contacts.
Contact record with highlights, properties and a unified activity timeline of ad clicks, page views, forms and payments
Record page. Ad clicks, visits, forms and payments on one timeline, plus notes, tasks and attribution.
Pipeline kanban with New lead, Qualified, Call booked and Proposal columns, weighted value and rotting counts
Pipeline. Drag by mouse, touch or keyboard. Payments move contacts to Won automatically.

Also: My tasks, CSV import with a preview before anything is written, and duplicate review and merge with re-attribution.

Reports, PDFs and AI documents

Report library with executive summary, weekly performance, attribution model comparison, LTV and cohorts, and wasted spend reports

Eleven print-ready PDF reports: executive summary, weekly performance, attribution model comparison, LTV and cohorts, wasted spend, channel mix, lead source quality, creative and ad leaderboard, funnel and time to convert, pipeline and CRM activity and profit and refunds.

Your logo on the masthead, a methodology appendix, a "Prepared for" watermark and a fingerprint on every page that anyone can check at /verify. Download, call the API, or schedule weekly or monthly emails. Rendered in-process: no headless browser, no extra container. docs/REPORTS.md

AI document generator. Pick one of 12 prompt templates (monthly client report, board update, post-mortem, budget memo, Meta vs Google, lead quality audit, stand-up, case study, creative brief, quarter review, funnel leaks, refunds) or write your own. Your model writes the words; AdLedger draws every KPI, table and chart from SQL, removes any sentence with a number that is not in the data, and lays it out as a branded, fingerprinted PDF with an in-app preview.

Insights and Ask AI

Action cards (move budget, room to grow, revenue drop, CAC up) where every figure links to its source row, a weekly report marked All numbers verified, and Ask: plain-language questions answered from read-only SQL tools, with the table each answer came from. Any number a model invents is flagged. Works with no model at all, a local model (Ollama, LM Studio) or OpenAI, Anthropic, Gemini, OpenRouter, DeepSeek and any OpenAI-compatible endpoint.

Insights action cards: move budget, room to grow and a revenue drop, with every figure linked to its source

Alerts, sharing, goals and speed

  • Alert rules on CAC, CPL, ROAS, spend, revenue or leads with cooldowns, plus optional anomaly detection.
  • Notifications by email, Slack, Discord, Microsoft Teams, SMS (Twilio) or signed webhook.
  • Share links: read-only aggregate dashboards with locked filters, an expiry, a view count and one-click revoke. Contact details are never shared.
  • Targets and goals with pacing and projection to period end.
  • Ctrl K / ⌘K finds any page, contact or campaign; G then a letter jumps between pages; ? lists shortcuts.
  • Product tour: a 2-minute spotlight tour on first sign-in that shows each person only what their role can open.
  • Your colours: 20 solid themes and 10 gradients for the whole organization, all passing WCAG AA. Profit and loss stay green and red.
  • Custom roles with per-page and per-action permissions, next to five built-in roles (owner, admin, analyst, viewer, client).
  • Installable on your phone (PWA) with a bottom tab bar, and a dark mode that follows your system.

Developers: API, webhooks, recipes

Developers area with a quickstart, API keys, webhooks and delivery health

A dedicated Developers area (owners and admins by default) for wiring AdLedger into your own tools:

  • API keys with scopes (reports:read, mcp, contacts:read, contacts:pii, ingest:write), optional expiry, stored hashed.
  • Signed outbound webhooks for lead.created, contact.created, contact.updated, payment.succeeded and payment.refunded: HMAC-SHA256 signatures, retries with backoff for about two days, a 30-day delivery log with redeliver, Send test event, masked emails unless you opt in, private URLs blocked. docs/WEBHOOKS.md
  • API reference generated from the OpenAPI 3.1 spec, with curl, JavaScript and Python examples. docs/API.md
  • Recipes you can copy: SMS a new lead in seconds (Twilio), send a Cal.com booking link, shout out payments in Slack, connect Zapier, Make or n8n, or append rows to Google Sheets.
# Pull leads with a read key
curl -H "Authorization: Bearer al_..." https://your-adledger/api/v1/leads

MCP server for AI assistants

Ask Claude, Cursor or any MCP client "which ads made money last month?" against your own ledger. Create a key in Developers → API keys, then:

claude mcp add --transport http adledger https://your-adledger/api/mcp --header "Authorization: Bearer al_..."
14 read-only tools

get_overview, get_performance, find_wasted_spend, compare_periods, get_platform_breakdown, get_timeseries, search_campaigns, contact_stage_funnel, list_contacts, get_contact_journey, get_ad_receipt, get_latest_insights, get_sync_status, list_integrations.

Every tool is annotated read-only and a test proves none of them changes data. Emails are masked. Setup for Claude Desktop and Cursor: docs/MCP.md.

Integrations

Connected from Settings → Integrations, with step-by-step instructions on each card and a mock mode for every connector.

Ad platformsMeta Ads, Google Ads, Microsoft Ads, TikTok Ads, LinkedIn Ads, Pinterest Ads, Snapchat Ads, Reddit Ads, X Ads. Anything else by CSV or the Spend API.
Payments and storesStripe (paste one key, the webhook is created for you), Shopify, WooCommerce, Paddle, Lemon Squeezy, Razorpay, PayPal, Chargebee, Recurly, Gumroad, Cashfree, Instamojo, PhonePe. Anything else by CSV or the Conversions API.
CRMsWon deals from HubSpot and Pipedrive.
Lead formsAny form with data-adledger-lead, Typeform, Tally, Webflow, Zapier or Make webhooks, native Meta Lead Ads, Google Ads lead forms, TikTok Lead Generation and WhatsApp click-to-chat.
Your websiteOne <script> tag (2.4 KB gzipped), a WordPress/WooCommerce plugin, a Shopify custom pixel, a GTM template and guides for Webflow, Wix, Squarespace, Framer and Next.js.
Back to the ad platforms (beta)Consent-aware conversion upload to the Meta Conversions API and Google Ads, hashed identifiers only.
NotificationsEmail, Slack, Discord, Microsoft Teams, SMS (Twilio), signed webhook.

Connectors other than Meta, Google Ads and Stripe are in beta: tested against real-format fixtures, not yet verified on live accounts. Details: docs/CONNECTORS.md.

Screenshots

OverviewRevenue and ROAS by attribution model
OverviewRevenue and ROAS under first touch, last touch and linear per campaign, with journey starters and closers
Time to convertTime to money and pause drafts
Lag histograms from first touch to lead and payment, with a recommended attribution windowMedian days from first click to payment, pause drafts for Meta and Google Ads Editor, and payback lag by campaign
Ask your numbersSecurity policy and posture checklist
Ask panel with suggested questions answered from the ledgerSecurity policy checklist: encryption key storage, HTTPS, two-factor coverage, session limits and audit verification
30+ integrationsGuided setup checklist
Integrations catalogSetup checklist that adapts to your website builder, payment tools and ad platforms
More: tracking, team, alerts, audit log, two-factor sign-in, notifications, report verification
Tracking snippet and consent modesMembers and roles
Tracking settingsMembers and roles
Alert rules and anomaly detectionHash-chained audit log
Alerts settingsAudit log with export and verify chain
Two-factor sign-in and devicesNotification channels
Account security with two-factor sign-in and signed-in devicesNotification channels
Verify a PDF report
Public verify page for report fingerprints

On your phone: installable as an app, with a floating tab bar and a one-tap filter sheet.

Overview on a phone Live on a phone Performance on a phone Integrations on a phone

Security and compliance

GDPR-ready tooling SOC 2-aligned controls Free two-factor sign-in Hash-chained audit log AES-256-GCM for stored credentials Non-root container image CodeQL and image scanning

AdLedger is self-hosted software, so it holds no certification and makes no compliance claim on your behalf. It ships GDPR-ready tooling and SOC 2-aligned controls to help you meet GDPR, UK GDPR, CCPA/CPRA and India's DPDP; when you self-host, you are the data controller. SOC 2 and ISO 27001 assess the organisation that runs a service, so they apply to you, not to the project. What AdLedger gives that organisation is controls and evidence that make those audits easier.

FrameworkWhat AdLedger providesGuide
GDPR / UK GDPRConsent modes, export, erasure, retention, hashing, masking, audit trailArt. by Art.
CCPA / CPRAGlobal Privacy Control, consent-aware uploads, access and deleteRequirements
ePrivacy / PECRConsent-required and cookieless pixel modes, banner snippetsCookies
SOC 2Controls that map to CC6 (access), CC7 (monitoring), CC8 (change), C1 and P criteriaMapping
ISO/IEC 27001:2022Supports the relevant Annex A controlsMapping
OWASP Top 10, ASVS, CIS DockerSelf-assessed against the public lists; no formal verificationTables

Not covered: HIPAA and health data, and children's data. Card data never touches AdLedger (your payment provider holds it). See what is not covered and the go-live checklist.

Every control, by area
AreaControls
Sign-inFree two-factor sign-in (TOTP + recovery codes) that owners can require org-wide, with a documented break-glass for a locked-out owner. scrypt passwords under a NIST SP 800-63B-4 policy.
SessionsHashed tokens, idle timeout and maximum lifetime, a device list with sign out one or everywhere, new-device emails.
AccessFive built-in roles plus custom roles with per-page and per-action permissions. Contact emails masked by role, with every reveal audited. Separate permissions for aggregate CSVs, contact exports and PDFs.
PIIRaw emails only in the contacts table; SHA-256 hashes everywhere else. IPs truncated. Stored payloads redacted.
Secrets and keysConnector credentials and 2FA secrets encrypted with AES-256-GCM. API keys stored hashed, with scopes and optional expiry.
AuditTamper-evident, hash-chained audit log with Verify, filters and CSV export. Security alerts for new keys, webhooks, role changes, 2FA resets, bulk exports and new-device sign-ins.
ConsentPixel consent modes (opt-out, consent required, cookieless) and Global Privacy Control. Conversion uploads carry consent signals, and people who said no are never uploaded.
Data rightsPer-contact export and erasure (UI and API), full workspace export, raw-event retention.
Leak deterrenceWatermarked, fingerprinted PDFs verifiable at /verify, an export log, aggregate-only share links.
Web and supply chainCSP and security headers, SSRF guards, signed webhooks. CodeQL, dependency review, pnpm audit, Trivy image scans, Dependabot, SBOM and provenance on release images.
Disclosure/.well-known/security.txt on every install and private vulnerability reporting (SECURITY.md).

Read the Trust and security page for the mechanisms and the hardening checklist, and the Compliance guide for the framework mappings and the statements that are safe to make about your install.

Architecture

One Next.js app and PostgreSQL. The dashboard, REST API, pixel collector, webhooks, MCP server, live stream, PDF rendering and background jobs all run in a single container.

 your website ──al.js──▶ /api/v1/collect ─────┐
 forms, CRMs ──webhook─▶ /api/v1/webhooks ────┤
 Stripe, stores ─webhook▶ /api/v1/webhooks ───┼──▶  AdLedger (Next.js)  ──▶  PostgreSQL 16
 ad platforms ◀── scheduled sync / uploads ───┤        ▲ dashboard, /share, /verify
 Claude, Cursor ──MCP──▶ /api/mcp ────────────┘        └──▶ signed webhooks out

Stack: Next.js 16 · React 19 · TypeScript · PostgreSQL 16 (Drizzle ORM, embedded PGlite for trials) · Tailwind CSS v4 + shadcn/ui · Recharts · react-pdf · Vercel AI SDK · MCP SDK · vitest · Playwright. Details and design decisions: docs/ARCHITECTURE.md.

Documentation

DocWhat's in it
FeaturesEvery page and setting, grouped
Self-hostingInstall options, HTTPS, upgrades, backups, configuration
ConnectorsSetting up each integration, UTM templates, mock mode
Site-builder guidesWebflow, Wix, Squarespace, Framer, Next.js, GTM, Shopify, WordPress
PixelThe tracking script, its API and consent
ReportsPDF reports, AI documents, schedules, watermarks and verification
API · Webhooks · MCPREST API, signed outbound webhooks and recipes, AI assistant tools
Trust and securityControls, privacy, hardening checklist, disclosure
ComplianceGDPR, CCPA, SOC 2, ISO 27001, OWASP and CIS mappings, go-live checklist, safe claims
FAQData, accuracy, iOS, cost, 2FA lockout, compliance questions
Architecture · Product · RoadmapHow it's built, who it's for, what's next

Roadmap

What is shipped and what is next lives in docs/ROADMAP.md. Ideas and votes are welcome in issues.

Contributing

pnpm install
pnpm dev                   # http://localhost:3000, embedded database, no Docker needed
pnpm test                  # vitest on an embedded Postgres, every connector mocked
pnpm lint && pnpm typecheck
pnpm build && pnpm e2e     # Playwright browser tests with axe accessibility checks

Bug reports, connectors, report kinds and docs fixes are welcome. Start with CONTRIBUTING.md and the roadmap. Found a security issue? See SECURITY.md.

License

AdLedger is source available under the Functional Source License, FSL-1.1-ALv2, a "Fair Source" licence. It is not an OSI-approved open source licence.

  • What you can do: use it and self-host it for free, including for a business or an agency running its own ads, read and modify the code, and contribute changes back.
  • What you can't do: sell it, sell a modified version, or offer it (or something substantially similar built from it) as a competing product or hosted service.
  • After two years: each version automatically converts to the permissive Apache-2.0 licence, counted from the date that version was released.

Contributions are accepted under the same licence (see CONTRIBUTING.md). The name and logo are covered by TRADEMARKS.md. The WordPress plugin in integrations/wordpress is a separate work licensed GPL-2.0-or-later, as WordPress.org requires.


Shubham Vankalas

Built by Shubham Vankalas, as a free-to-self-host tool for founders who want to know which ad paid off.

If AdLedger shows you which ad made you money, give it a star. It helps other founders find it.

Star history chart for AdLedger

Website · Issues · Contribute

ad-attribution
analytics
conversion-tracking
crm
docker
fair-source
google-ads
marketing-attribution
mcp
meta-ads
nextjs
postgresql
revenue-tracking
roas
self-hosted
source-available
stripe

Languages

TypeScript

93.6%

HTML

2.3%

CSS

1.8%

JavaScript

1.5%