Your Segment workspace already sees logged-in users, form submissions, and product events. What it does not see is the 90%+ of your website traffic that never logs in, never fills a form, and disappears into “Anonymous User 9f3b41”. That is the hole Leadpipe fills: pushing identified visitor data straight into Segment so your CDP fans it out to every downstream tool at the same time.
I am Elene, and this is the recipe I give data teams who want Leadpipe to behave like a first-party identity source inside Segment. Setup is about 30 minutes. By the end, your CDP has identify calls on previously-anonymous visitors, track calls on their page views, and your warehouse, email tool, and analytics all get the same signal.
What you will build
A pipeline where every identified US B2B visitor triggers a Segment identify call and one or more track calls via Segment’s HTTP API, populating traits and event properties that fan out to every destination you have connected (warehouse, Iterable, Mixpanel, LinkedIn, Facebook, Customer.io, etc.).
Prerequisites
| Requirement | Notes |
|---|---|
| Leadpipe account | Start free with 500 identifications |
| Segment workspace | Any tier with a Source that accepts HTTP API |
| Segment write key | From the HTTP API source you create in Step 1 |
| Zapier or your own middleware | Optional no-code path |
| Time | 30 minutes |
If you are not on Segment but on RudderStack, Freshpaint, or Jitsu, the pattern is nearly identical. Both of those tools expose the same identify and track verbs. The Iterable journeys recipe shows a direct-to-destination variant for teams without a CDP.
How the layers connect
Visitor identified on your site
│
▼
Leadpipe webhook (First Match / Every Update)
│
▼
Your middleware (or Zapier)
├─ Segment identify(userId, traits)
└─ Segment track(userId, "Website Session", properties)
│
▼
Segment fans out to destinations:
Warehouse → identified_visitors table
Iterable → user update + custom event
Mixpanel → profile + event
LinkedIn Ads → matched audience
Customer.io → segment membership
Webhook dest → any custom downstream
The advantage of running Leadpipe through Segment rather than direct to each tool is that you wire once and every new destination gets the signal for free. This is exactly the role Segment was built for.
Step 1: Create the Segment source
In Segment Workspace:
- Go to Sources, Add Source, pick HTTP API.
- Name it “Leadpipe identity”.
- Copy the Write Key. You will use this in the middleware.
- Connect destinations you want to receive the identity data. At minimum: your warehouse. Add Iterable, Customer.io, Mixpanel, LinkedIn Ads, Facebook Conversions as needed.
Segment bills per Monthly Tracked User (MTU) on most plans. Identified visitors from Leadpipe count as MTUs if you assign them a userId. If your contract is tight, batch updates or sample. For most teams, the identified subset (30-40%+ of US B2B traffic) is comfortably inside normal MTU budgets.
Step 2: Decide on your userId strategy
This is the decision that determines how clean your Segment data is for the next three years. Two options:
| Strategy | userId value | Pros | Cons |
|---|---|---|---|
| Email as userId | visitor’s business email | Simplest join across tools, matches most destinations out of the box | Breaks if visitor changes email; PII in userId |
| Hashed email (SHA256) as userId | sha256(lowercased email) | PII-safe, still joinable to destinations that accept hashed emails | Mixpanel / warehouse need the hash field to join |
If you already have an app with a product-side userId, you want a third option: if the Leadpipe email matches an existing app user (lookup before the identify call), use that user’s userId. Otherwise fall back to hashed email.
For most marketing-only teams, hashed email is the safest default.
Step 3: Configure Leadpipe webhooks
In Leadpipe: Settings, Integrations, Webhooks, Add Webhook.
- Destination URL: generated in Step 4.
- Trigger: First Match for the identify call. Add a second webhook with Every Update if you want
trackcalls on return visits. - Fields: all.
Sample payload (full schema in our webhook payload reference):
{
"email": "james.park@northwind.io",
"first_name": "James",
"last_name": "Park",
"phone": "+1-212-555-0184",
"company_name": "Northwind Labs",
"company_domain": "northwind.io",
"company_industry": "Logistics SaaS",
"company_employee_count": 320,
"company_linkedin_url": "linkedin.com/company/northwind-labs",
"job_title": "Director of Demand Generation",
"seniority": "Director",
"department": "Marketing",
"linkedin_url": "linkedin.com/in/jamespark",
"city": "New York",
"state": "New York",
"country": "US",
"page_url": "/pricing",
"pages_viewed": ["/", "/features/identification", "/pricing"],
"visit_duration": 198,
"intent_score": 74,
"matched_topics": ["visitor identification", "intent data"],
"referrer": "google.com",
"return_visit": true
}
GDPR defaults. For EU and UK visitors, Leadpipe returns company-level identification unless the visitor has given affirmative consent. Those payloads have company fields and no email. You cannot emit a normal identify call without an identifier, so for EU traffic we either skip the Segment call or emit an identify against a domain-scoped anonymous ID like company:${domain}. The right choice depends on your compliance policy. See our GDPR-compliant visitor identification post for the detailed take.
Step 4: Middleware that emits Segment calls
Zapier can do this with two Webhooks actions (Custom Request POST to https://api.segment.io/v1/identify and /v1/track), but the direct middleware path is cleaner because you can hash the email, compute derived traits, and respect GDPR defaults in one place.
// POST /leadpipe-webhook → Segment HTTP API
// Env: SEGMENT_WRITE_KEY
import fetch from 'node-fetch';
import crypto from 'crypto';
const auth =
'Basic ' + Buffer.from(process.env.SEGMENT_WRITE_KEY + ':').toString('base64');
const headers = { Authorization: auth, 'Content-Type': 'application/json' };
function sha256(input) {
return crypto.createHash('sha256').update(input.toLowerCase().trim()).digest('hex');
}
export async function handler(req) {
const v = req.body;
const domain = v.company_domain?.toLowerCase().replace(/^www\./, '');
// GDPR: EU/UK without email arrives as company-level. Decide behavior.
if (!v.email) {
if (!domain) return { statusCode: 200, body: 'no id' };
// Emit a company-level identify only if your policy allows
await fetch('https://api.segment.io/v1/group', {
method: 'POST',
headers,
body: JSON.stringify({
anonymousId: `company:${domain}`,
groupId: domain,
traits: {
name: v.company_name,
domain,
industry: v.company_industry,
employees: v.company_employee_count,
source: 'leadpipe',
level: 'company-only (GDPR default)',
},
}),
});
return { statusCode: 200, body: 'company-level only' };
}
const userId = sha256(v.email);
const now = new Date().toISOString();
// identify
await fetch('https://api.segment.io/v1/identify', {
method: 'POST',
headers,
body: JSON.stringify({
userId,
traits: {
email: v.email,
firstName: v.first_name,
lastName: v.last_name,
phone: v.phone,
title: v.job_title,
seniority: v.seniority,
department: v.department,
linkedinUrl: v.linkedin_url,
city: v.city,
state: v.state,
country: v.country,
company: {
name: v.company_name,
domain,
industry: v.company_industry,
employees: v.company_employee_count,
linkedinUrl: v.company_linkedin_url,
},
source: 'leadpipe',
lastSeenAt: now,
intentScore: v.intent_score,
intentTopics: v.matched_topics,
},
context: { ip: req.headers['x-forwarded-for']?.split(',')[0] },
}),
});
// group (account-level)
if (domain) {
await fetch('https://api.segment.io/v1/group', {
method: 'POST',
headers,
body: JSON.stringify({
userId,
groupId: domain,
traits: {
name: v.company_name,
domain,
industry: v.company_industry,
employees: v.company_employee_count,
},
}),
});
}
// track
const eventName = v.return_visit ? 'Website Return Visit' : 'Website Session';
await fetch('https://api.segment.io/v1/track', {
method: 'POST',
headers,
body: JSON.stringify({
userId,
event: eventName,
properties: {
pageUrl: v.page_url,
pagesViewed: v.pages_viewed,
pagesViewedCount: (v.pages_viewed || []).length,
visitDuration: v.visit_duration,
intentScore: v.intent_score,
intentTopics: v.matched_topics,
referrer: v.referrer,
returnVisit: v.return_visit,
},
timestamp: now,
}),
});
return { statusCode: 200, body: 'ok' };
}
Three notes:
- Segment’s HTTP API accepts both
userIdandanonymousId. UseuserIdonce you have one. Fall back toanonymousIdonly for cases where you deliberately cannot resolve identity. - The
groupcall assigns the user to an account in Segment. Destinations that support account-level traits (Customer.io, warehouse, Mixpanel with Accounts) will receive it. - Do not send
context.ipif your DPA prohibits it. For EU traffic, skip IP entirely.
Step 5: Segment destination setup
Once calls are flowing into your Segment source, open Destinations and connect the downstream tools. Key ones worth wiring:
| Destination | What happens |
|---|---|
| Warehouse (Snowflake, BigQuery, Redshift) | identified_visitors table + website_session table for BI/attribution |
| Iterable | User update + custom event, fuel for journeys (see the Iterable journeys recipe) |
| Customer.io | User attributes + event, for lifecycle campaigns |
| Mixpanel | Profile + event, for funnel analysis |
| LinkedIn Ads Matched Audiences | Matched audiences for retargeting (complements the LinkedIn Ads integration) |
| Google Ads | Enhanced conversions if you are tracking high-intent sessions |
| Facebook Conversions API | Hashed-email audience expansion |
| Webhook destination | Any custom downstream (including other CRMs) |
The real payoff: one Leadpipe integration feeds every destination Segment supports. Swap a destination in and out without touching Leadpipe.
What this looks like in practice
James, Director of Demand Generation at Northwind Labs (320 employees, logistics SaaS in New York), read your identification pillar post two weeks ago. He returns this morning, searches for “leadpipe pricing,” lands on pricing, reads for 3 minutes 18 seconds.
- Leadpipe identifies him. First Match webhook fires.
- Middleware computes userId = sha256(“james.park@northwind.io”). Emits:
identifywith traits including title, seniority, company (Northwind Labs, 320 employees, Logistics SaaS), lastSeenAt, intentScore 74, intentTopics [“visitor identification”, “intent data”].groupassigning James togroupId: "northwind.io".trackevent “Website Return Visit” with properties pageUrl, pagesViewed, visitDuration.
- Segment fans it out.
- Warehouse: row inserted into
identified_visitorsandtrackstables. RevOps runs their nightly attribution job. - Iterable: user updated, “Website Return Visit” event triggers a journey for mid-market demand gen leads.
- Customer.io: James is added to a “High-intent mid-market” segment, which pushes a sequence.
- LinkedIn Ads: James’s hashed email goes into the “Pricing page return visitors” matched audience.
- Mixpanel: funnel stage updated, shows in the weekly growth review.
- Warehouse: row inserted into
- Four hours later, James replies to Iterable’s email. Thirty minutes after that, the AE opens the warehouse-fed Looker dashboard and sees Northwind in the top-5 hot accounts row.
That is what a CDP loop looks like when Leadpipe is the first step.
Troubleshooting and edge cases
Duplicate users in destinations. Use a consistent userId strategy. If you send email sometimes and hashed email other times, destinations will treat them as different users. Pick one and stick with it.
Segment rate limits. The HTTP API allows 500 requests per second per workspace. For most Leadpipe volumes this is not an issue. If you approach the limit, batch into arrays via the batch endpoint (POST /v1/batch) which accepts up to 500 events per request.
Warehouse schema drift. Segment’s warehouse connector will evolve the schema when new traits appear. If you add a new field to your Leadpipe middleware, Segment will back-fill forward but not backward. Plan column names carefully; once in the warehouse they are sticky.
EU/UK company-level events. The middleware above uses anonymousId: "company:<domain>" plus a group call. Some destinations will not accept an anonymousId without a userId. If a destination drops these events, that is by design; the warehouse and LinkedIn matched audiences will still receive them. For more on how GDPR shapes this flow, see our GDPR compliance post.
Over-eventing a single page view. If you enable Every Update webhooks and your middleware emits a track per page change, a single long session can generate a dozen events. Debounce in middleware: only emit a new track if the page URL changed or visit_duration grew by over 60s.
Hashed vs unhashed email for downstream destinations. Some destinations (LinkedIn Ads, Google Ads, Facebook) accept hashed email. Others (Iterable, Customer.io, Mixpanel) prefer plain email. Send plain email as a trait (email on identify) and keep userId as hashed, and you cover both cases.
Unexpected PII in traits. Make sure your Segment source is configured with appropriate PII handling (allow/deny lists, regional processing). Never send net worth, age range, or other consumer-grade Leadpipe fields into a B2B marketing CDP if your DPA does not allow it. The default recipe above stays on job, company, location, engagement fields.
Extending the recipe
- Pair with the Iterable journeys recipe so Segment feeds Iterable and you can test with or without Segment in the middle.
- Push the same stream into Slack alerts so sales sees the hit in real time while Segment fans out to warehouse and lifecycle tools.
- If you are building AI workflows, the Leadpipe MCP server can query the identity graph directly while Segment handles the operational events, giving your agents both the ambient signal and the query-time lookup.
- Combine with Clay enrichment between Leadpipe and Segment if you want tech stack, revenue, or waterfall-enriched phone in your identify traits.
- If you run CRM writes alongside Segment, our Salesforce integration gives you the mirror pattern for the CRM side.
Why CDP-first is the cleanest setup for larger teams
When your data team maintains Segment, having Leadpipe be another source rather than a bespoke integration is what keeps the stack sane. One schema, one governance model, one place to turn a destination on or off. And when a future you wants to add a new destination (say, Customer.io for messaging), you do not need to touch Leadpipe at all.
The identity layer is upstream of every destination. Make it replaceable, make it observable, make it yours.
Every plan ships with the same identity graph, 23 REST endpoints, webhooks, and a 27-tool MCP server. Start in 5 minutes →