ingestlayer/blog

all posts
Post#playbook

Capture every app lead straight into a Notion database.

Your leads happen in your app. Your CRM is a Notion database. Here's the pipe that turns a form submission into an enriched, qualified row.

ben7 min read


If you run a small team, there is a good chance your CRM is a Notion database — a row per lead, a few properties, and a board view someone checks on Monday. Getting leads back out of it is easy. The hard part is getting them in.

Leads happen in your app: a signup, a demo request, a form on the pricing page. Your Notion database has no idea until someone copies an email out of a notification and types a new row by hand — or wires up a zap that dumps the raw form fields in and leaves you a row that says j.doe@acme.io and almost nothing else.

what a lead row should actually look like

Picture the row you would actually want to wake up to. A real name. The company behind the email domain. Where the lead came from. And some honest signal about whether it is worth a call today or a nurture email next month. That is the difference between a database you triage and a database you ignore.

Turning j.doe@acme.io into “Jane Doe, Acme, came from the pricing page, reads as a hot lead” is exactly the work nobody wants to do by hand. But none of it is creative work — it is mechanical, every time. Which means something else can do it before the row is ever written, so the only rows that reach Notion are the ones already worth looking at.

three moves before the row is written

Between the form submission and the Notion row there is room for a few cheap, boring operations. Three of them do most of the work.

dedupe handles the person who submits the form twice because the first click felt slow. dedupe keys on the email and collapses repeats inside a window, so one person is one row instead of three you have to merge later.

enrich is the step that earns its keep. enrich.person resolves an email into a real name, and enrich.company turns the domain into the company behind it. The bare address becomes a lead you recognize, without you opening a single tab.

classify is the one that decides what you do next. Instead of writing brittle rules about what counts as a good lead, you hand the enriched event to a model with a typed set of labels and let it read the room. classify can look at the person, the company, and the form they filled and tell you hot_lead, evaluating, or tire_kicker — and now that label is just another property on the row.

the whole thing as one file

Put the three moves together and the path from your app to your Notion database becomes this — the same pipeline as the diagram you'd see in the app, or as the file you commit. Flip between them.

representation

01source

sourcesdk.eventTypeScript SDK
matchlead.captured

02pipeline · 4 steps

  • 01CTLdedupekey $event.email · within 24h
  • 02ENRenrich.person$event.email → name
  • 03ENRenrich.company$person.domain → company
  • 04ENRclassifyintent · hot_lead / evaluating / tire_kicker

03destinations · 3

  • tonotion.dbNotion
    target_id$env.NOTION_LEADS_DB
  • toslackSlack
    channel#sales
    when$classify.intent == "hot_lead"
  • towarehouse.pgPostgres
    tableevents.leads

One event comes in, three destinations go out, each shaped for who is on the other end. Notion gets a clean, enriched row with the intent already filled in. The #sales channel only hears about it when the lead is hot, so the ping is rare enough to still mean something. And Postgres keeps every lead, qualified or not, because a warehouse never gets tired of reading and you will want the full funnel later.

how ingestlayer does this

Everything above is real. Notion is a destination, so a qualified event becomes a row in your database with the properties you map. dedupe, enrich, and classify are real actions you stack between a source and a destination — you point your app's events at the pipeline, compose the steps this lead needs, and let the result fan out to Notion, Slack, and the warehouse at once.

Leads into a CRM are one shape of the same problem behind Slack pings without the noise: something arrives with more volume than attention, and the job is to do the thinking once, in the pipe, before it reaches a place humans read. Notion happens to be a lovely place to read. There are other use cases, but a CRM you can actually trust to be current is a good one to start with.


Read next

Get a Slack ping for every signup, without the noise.

Wiring a webhook to Slack so it pings on every signup takes five minutes. Making those pings worth reading is the actual job. Here's the pipe in between.

← back to all posts