Skip to content
LeadSheet for Google Sheets

KEEP LEAD
ATTRIBUTION
IN YOUR SHEET

KEEP LEAD
ATTRIBUTION
IN YOUR SHEET

LeadSheet turns any Google Sheet into a CRM that captures UTMs, GCLIDs, FBCLIDs, and session data from every lead — and sends offline conversions back to Google Ads automatically when a deal closes.

  • Google Sheets native
  • No SaaS subscription
  • Google Ads offline conversions
  • 10-minute setup
  • Optional server-side ingestion
LeadSheet CRM pipeline view in Google Sheets

One script, four operational surfaces

  • Capture first-touch and last-touch attribution before the lead reaches your sheet.

  • Sync all events to a structured CRM pipeline view every 15 minutes.

  • Push conversion signals to Google Ads automatically when a deal closes.

  • Import historical leads and archive cold ones without losing data.

LeadSheet CRM tab showing pipeline and attribution columns

47 columns of attribution data captured per lead — UTMs, GCLIDs, device, page path, and sha256 identity hashes.

Why CRM data goes stale

ATTRIBUTION
BREAKS AFTER
THE FORM

Attribution usually breaks after the form, not at the ad platform. LeadSheet is built for the point where Google Sheets actually needs the source trail: the moment a lead submits a form, calls, or walks in — and the moment they convert, weeks or months later.

Built for
production
conditions

  • Form submissions arrive without UTMs because the landing page cached before the click.

  • Walk-in and phone leads have no digital attribution at all — they need a manual entry path.

  • The same person submits multiple forms across sessions — duplicates pollute the pipeline.

  • Operators overwrite source data by accident — attribution is gone before the deal closes.

  • Google Ads needs a conversion signal 90 days after the click — CRM data must persist that long.

Need the schema reference, setup guide, and configuration docs first?

Open the DocsBrowse GitHub source
Core capabilities

CAPTURE, SYNC,
PIPELINE, AND
EXPORT

LeadSheet is organized around the surfaces operators actually use: event capture, CRM pipeline, Google Ads export, and historical import. Each can be adopted in phases.

Raw tab

Every lead event writes one row to the Raw tab. Rows are never modified or deleted. 47 columns capture timestamps, UTMs, GCLID, fbclid, device, page path, known contact data, and sha256 hashes for identity resolution.

CRM tab

30 columns organized into four groups: system data (locked), identity (editable), tracking attribution (locked), and operator pipeline (editable). Operators work in the green columns — stage, value, owner, follow-up date, notes.

Google Ads export

When an operator moves a lead to the conversion stage, an onEdit trigger writes a row to ExportQueue. A composite queue_id prevents double-uploads. The Python worker reads ExportQueue and calls the offline conversion API.

Dashboard

Four KPI cards (active leads, clients, follow-ups today, leads this week), a pipeline funnel bar chart, a leads-by-source pie chart, and a today's follow-up list that auto-updates as the CRM changes.

Import & archive

Paste historical lead data into an Import tab and run importHistoricalLeads(). Phone and email deduplication prevents collisions with live data. Cold leads move to CRM_Arquivo on the first of each month.

Analyst reviewing lead attribution and CRM pipeline data
Where attribution breaks in practice

THE FAILURE MODES
ARE NORMAL SALES
CONDITIONS

Cached forms, walk-in leads, repeat submissions, and operators editing source data are not edge cases — they are everyday conditions in a working sales pipeline. LeadSheet treats them as first-class implementation problems instead of workarounds.

LeadSheet ExportQueue tab showing pending Google Ads conversions
  • Capture and identity resolution stay separate from pipeline editing.

  • CRM and Google Ads export can be adopted before server-side ingestion.

  • Manual Google Form for walk-ins works from day one.

  • Attribution columns are locked — operators cannot overwrite them.

Recommended rollout sequence

  • Run setupCrmSheet() and paste the scripts. Takes 10 minutes.

  • Add the Raw tab to your existing form handler — just a JSON POST.

  • Use the manual Google Form for walk-ins and phone leads from day one.

  • Wire the Python worker only when you have enough conversions to warrant it.

That sequence keeps LeadSheet operational on day one while leaving room for the full attribution and export stack later.

Operational proof

SHEET SURFACES
THAT MATCH THE
SALES WORKFLOW

LeadSheet Dashboard with KPI cards and pipeline funnel chart

Dashboard

  • KPI overview

See active leads, clients, and today's follow-ups at a glance

The Dashboard tab keeps four live KPI cards and a pipeline funnel visible where the team already works — inside the sheet, not in a separate reporting tool.

LeadSheet CRM tab showing pipeline columns and attribution data

CRM tab

  • Pipeline management

Manage the full sales pipeline with locked attribution and editable pipeline columns

Operators work in the green columns — stage, value, owner, follow-up date, notes. System and tracking columns are protected so attribution cannot be accidentally overwritten.

LeadSheet ExportQueue tab with pending conversion rows

ExportQueue

  • Google Ads offline conversions

Push conversion signals to Google Ads automatically when a deal closes

When an operator moves a lead to the conversion stage, an onEdit trigger builds a composite queue_id and appends a row to ExportQueue. No manual CSV uploads.

LeadSheet Raw tab showing 47-column event ledger

Raw tab

  • Event ledger

Every lead event writes one append-only row — the source of truth for all CRM data

The Raw tab is an append-only ledger. Rows are never modified or deleted. If the CRM ever gets out of sync, you rebuild it from Raw.

Technical FAQ

QUESTIONS TO SETTLE
BEFORE YOU
INSTALL

LeadSheet is designed for phased adoption. Teams can start with lead capture and CRM sync, then add the Google Ads export, historical import, or server-side ingestion when the operational model is ready.

  • Works without the Python worker on day one.

  • Supports form submissions, walk-ins, and phone leads from the start.

  • Keeps attribution, pipeline, and export decisions inside a single Google Sheet.

Built for phased rollouts from lead capture to CRM sync to Google Ads export rather than a one-shot setup.

Yes. Lead capture, CRM sync, pipeline management, and the Dashboard all work without the Python worker. ExportQueue rows will accumulate as pending and can be exported manually or wired up later.

The second submission produces a new Raw row. On the next sync, resolveLeadIdFromRawRow() derives the same lead_id from the same phone or email hash. findCrmRowByLeadId() finds the existing CRM row and updates only system columns. Operator columns are never touched.

Yes. Stage labels, owner names, and lost reasons are all driven by the CONFIG tab. Changing a label means updating CONFIG — no code changes, no deploy. The conversion trigger stage in CONFIG must match exactly what operators select in the dropdown.

The Python worker writes the error to export_error in ExportQueue and increments export_attempts. The most common reason is that the GCLID is older than 90 days. Conversions must be uploaded within the Google Ads attribution window.

No. LeadSheet handles the lead-ops side: capturing form and contact events, managing the sales pipeline, and uploading offline conversions to Google Ads. It is designed to work alongside GA4, GTM, and server-side GTM — not replace them.

INSTALL LEADSHEET
AND CLOSE THE
ATTRIBUTION GAP