Guides

Webhook Payload Reference: Every Visitor Data Field

Complete reference for Leadpipe webhook payloads. Every field, data type, example value, and how to use it in your AI agent, CRM, or automation workflow.

Nicolas Canal Nicolas Canal · · 8 min read
Webhook Payload Reference: Every Visitor Data Field

You’ve set up Leadpipe webhooks. Data is flowing into your endpoint. Payloads are arriving as structured JSON every time a visitor gets identified on your site.

But what does each field actually mean? When is visit_duration more useful than page_url? What’s the difference between a First Match and an Every Update trigger? And which fields should your AI agent actually care about?

This is the complete field reference — every data point Leadpipe sends via webhook, what type it is, what it looks like, and how to use it in your CRM, automation pipeline, or custom AI SDR.

Bookmark this page. You’ll come back to it.


Table of Contents


Webhook Trigger Types

Before diving into fields, you need to understand when data arrives. Leadpipe supports two webhook trigger modes, and the one you choose determines how much data you receive and how often.

TriggerWhen It FiresBest For
First MatchOnce per visitor, on first identificationCRM record creation, AI SDR outreach, Clay enrichment
Every UpdateEvery page view from an identified visitorBehavioral tracking, lead scoring, visit journey mapping

First Match is the default and what most teams should start with. It fires a single webhook the moment Leadpipe resolves an anonymous visitor into a known person. You get one clean payload per visitor — no duplicates, no noise. This is what you want for CRM enrichment, outreach triggers, and Slack alerts.

Every Update fires on each subsequent page view from an already-identified visitor. This gives you a full session journey but generates significantly more webhook volume. Use it when you need to track multi-page behavior, build real-time lead scoring, or feed granular engagement data into your data layer.

If you’re unsure, start with First Match. You can always switch later.


Complete Field Reference

Here’s every field Leadpipe includes in a webhook payload. All fields are present in every payload, but some may be null when data isn’t available for a particular visitor.

FieldTypeExampleDescriptionUse Case
emailstringjane@acme.comVisitor’s email addressPrimary contact method, CRM lookup, enrichment key
first_namestringJaneFirst nameEmail personalization, CRM record
last_namestringSmithLast nameEmail personalization, CRM record
company_namestringAcme CorpCompany nameICP checking, account matching
company_domainstringacme.comCompany website domainEnrichment key, Clay waterfall input
job_titlestringVP of MarketingJob title / roleICP qualification, seniority check, routing
linkedin_urlstringlinkedin.com/in/janesmithLinkedIn profile URLResearch, connection requests, enrichment
page_urlstring/pricingPage the visitor viewedIntent classification (pricing = high intent)
visit_durationnumber180Seconds spent on pageEngagement level (>60s = interested)
referrerstringgoogle.com/searchWhere the visitor came fromAttribution, source tracking
timestampstring2026-04-01T14:30:00ZWhen the visit occurred (ISO 8601)Timing outreach, freshness scoring
pages_viewedarray["/", "/pricing", "/case-studies"]All pages visited in sessionJourney analysis, intent depth
citystringSan FranciscoVisitor’s cityGeographic targeting
statestringCaliforniaVisitor’s stateTerritory routing
countrystringUSVisitor’s countryCompliance routing (GDPR for EU)
phonestring+1-415-555-0123Phone number (when available)Direct outreach, CRM enrichment

A few notes on field behavior:

  • email is the most reliable field. Leadpipe uses deterministic matching — no probabilistic guessing — so when an email is present, it’s a real match, not a statistical inference.
  • phone has lower availability than email. Expect it on roughly 40-60% of identified visitors. Still valuable when present — it’s a direct line.
  • pages_viewed on a First Match trigger contains all pages viewed before identification. On Every Update triggers, it contains the cumulative session journey.
  • visit_duration is measured in seconds. A visitor who spends 240 seconds on your pricing page is telling you something very different from someone who bounced after 8 seconds.
  • country is critical for compliance. EU visitors should be handled differently under GDPR — Leadpipe provides company-level data only for EU traffic.

Example Payloads

Here are three realistic payloads representing different intent levels. Use these to test your webhook receiver and classification logic.

High-Intent Visitor (Pricing Page, Long Duration)

This person hit the homepage, browsed features, and spent 4 minutes on pricing. They came from a Google search. This is the payload you want your AI agent to act on immediately.

{
  "email": "jane.smith@acme.com",
  "first_name": "Jane",
  "last_name": "Smith",
  "company_name": "Acme Corp",
  "company_domain": "acme.com",
  "job_title": "VP of Marketing",
  "linkedin_url": "https://linkedin.com/in/janesmith",
  "page_url": "/pricing",
  "visit_duration": 240,
  "referrer": "google.com",
  "timestamp": "2026-04-01T14:30:00Z",
  "pages_viewed": ["/", "/features", "/pricing"],
  "city": "San Francisco",
  "state": "California",
  "country": "US",
  "phone": "+14155550123"
}

What to do: Trigger immediate outreach. This person is actively evaluating. A personalized email referencing the pricing page within minutes has a 21x higher chance of converting than waiting even an hour.

Medium-Intent Visitor (Blog Reader, Multiple Pages)

A returning visitor reading educational content. They’re researching, not buying — yet. Two blog posts and a case study, 3 minutes total.

{
  "email": "mark.chen@globex.io",
  "first_name": "Mark",
  "last_name": "Chen",
  "company_name": "Globex Solutions",
  "company_domain": "globex.io",
  "job_title": "Head of Growth",
  "linkedin_url": "https://linkedin.com/in/markchen",
  "page_url": "/blog/visitor-identification-pricing",
  "visit_duration": 185,
  "referrer": "linkedin.com",
  "timestamp": "2026-04-01T09:15:00Z",
  "pages_viewed": ["/blog/visitor-identification-pricing", "/blog/rb2b-alternatives", "/case-studies"],
  "city": "Austin",
  "state": "Texas",
  "country": "US",
  "phone": null
}

What to do: Add to a 24-hour nurture sequence. Don’t blast them with a sales email while they’re still in research mode. Send something helpful that continues the conversation they’re already having with your content.

Low-Intent Visitor (Homepage Bounce)

Single page, short duration, no phone. They landed, glanced, and left. Still identified — still worth adding to your CRM — but not worth burning outreach tokens on right now.

{
  "email": "alex.rivera@startup.co",
  "first_name": "Alex",
  "last_name": "Rivera",
  "company_name": "Startup Co",
  "company_domain": "startup.co",
  "job_title": "Software Engineer",
  "linkedin_url": "https://linkedin.com/in/alexrivera",
  "page_url": "/",
  "visit_duration": 12,
  "referrer": "twitter.com",
  "timestamp": "2026-04-01T16:45:00Z",
  "pages_viewed": ["/"],
  "city": "Denver",
  "state": "Colorado",
  "country": "US",
  "phone": null
}

What to do: Add to CRM as a passive lead. If they return and hit a high-intent page later, the Every Update trigger will catch it.


Intent Classification Using Fields

Here’s a Python function that turns raw webhook fields into an actionable intent score. This is the same pattern used in the AI SDR data stack guide.

def classify_intent(payload):
    """Classify visitor intent from webhook payload fields."""
    page = payload.get('page_url', '')
    duration = payload.get('visit_duration', 0)
    pages = payload.get('pages_viewed', [])

    # High intent: pricing/demo pages, or deep + engaged sessions
    if any(p in page for p in ['/pricing', '/demo', '/contact']):
        return 'high'
    elif len(pages) >= 3 and duration > 120:
        return 'high'

    # Medium intent: evaluating content
    elif any(p in page for p in ['/case-stud', '/features', '/integration']):
        return 'medium'
    elif any('/blog' in p for p in pages) and duration > 90:
        return 'medium'

    # Low intent: everything else
    else:
        return 'low'

The logic is simple on purpose. page_url is the strongest signal — someone on /pricing is almost always high intent regardless of duration. visit_duration is the secondary signal — 2+ minutes across 3+ pages shows genuine engagement even if they haven’t hit a conversion page yet.

You can layer in cross-site intent data for even richer classification. A visitor who’s been researching “visitor identification tools” across multiple sites and is on your pricing page? That’s a five-alarm fire.


ICP Qualification Using Fields

Intent without qualification is noise. A student spending 5 minutes on your pricing page isn’t a lead. Combine intent classification with ICP checks using the person and company fields.

# Seniority keywords that indicate decision-maker authority
SENIOR_TITLES = ['vp', 'vice president', 'director', 'head of',
                 'chief', 'cmo', 'cro', 'ceo', 'coo', 'founder', 'owner']

# Domains to exclude (freemail, competitors, internal)
EXCLUDED_DOMAINS = ['gmail.com', 'yahoo.com', 'hotmail.com',
                    'outlook.com', 'competitor.com']

def passes_icp(payload):
    """Check if a visitor matches your Ideal Customer Profile."""
    title = payload.get('job_title', '').lower()
    domain = payload.get('company_domain', '').lower()
    country = payload.get('country', '')

    # Must have a business email domain
    if domain in EXCLUDED_DOMAINS or not domain:
        return False

    # Must be a decision maker or influencer
    if not any(kw in title for kw in SENIOR_TITLES):
        return False

    # GDPR: company-level only for EU visitors
    if country in ['DE', 'FR', 'GB', 'NL', 'ES', 'IT', 'SE', 'BE']:
        return False  # Route to company-level workflow instead

    return True

Now combine them:

def process_webhook(payload):
    intent = classify_intent(payload)
    is_icp = passes_icp(payload)

    if intent == 'high' and is_icp:
        return 'immediate_outreach'
    elif intent == 'high' and not is_icp:
        return 'add_to_crm'        # Good intent, wrong profile
    elif intent == 'medium' and is_icp:
        return 'nurture_24h'        # Right profile, still researching
    else:
        return 'crm_only'           # Log it, move on

This two-axis model — intent x qualification — is how the most effective AI SDR pipelines decide what to do with each visitor.


Routing Logic

Once you’ve classified intent and checked ICP fit, route the payload to the right destination. Here’s the decision tree:

Webhook received
  └── classify_intent()
       ├── HIGH + ICP match
       │    → Immediate AI outreach (email within minutes)
       │    → Slack alert to sales team
       │    → Create CRM contact (HubSpot/Salesforce/Pipedrive)

       ├── HIGH + ICP miss
       │    → Add to CRM (no outreach)
       │    → Tag as "high-intent, non-ICP" for review

       ├── MEDIUM + ICP match
       │    → 24-hour delayed nurture sequence
       │    → Enrich via Clay waterfall
       │    → LinkedIn connection request (optional)

       └── LOW (any ICP)
            → Add to CRM only
            → Monitor for return visits (Every Update trigger)

The key principle: never waste fast outreach on low-intent visitors, and never waste slow nurture on high-intent ones. A VP of Marketing on your pricing page right now does not need a drip campaign. They need a reply.

For a complete working implementation of this routing logic, see the full AI agent tutorial.


Ready to start receiving these payloads? Sign up for Leadpipe’s free trial — 500 identified leads, no credit card required. You’ll have webhooks firing in under 5 minutes.


Configuration Best Practices

Getting webhooks working is step one. Making them reliable and useful at scale takes a few more considerations.

1. Start with First Match triggers. Every Update is powerful but generates 5-10x more webhook volume. Get your pipeline working with one payload per visitor first, then upgrade when you need session-level granularity.

2. Use narrow segments during testing. Set your webhook to fire only for visitors on specific pages (e.g., /pricing, /demo) while you’re building and debugging your receiver. This keeps volume low and ensures every test payload is high-signal.

3. Return 200 immediately, process asynchronously. Your webhook endpoint should acknowledge receipt instantly and queue the payload for background processing. If your endpoint takes too long to respond, deliveries may time out. Here’s the pattern:

@app.post("/webhook/leadpipe")
async def receive_webhook(request: Request):
    payload = await request.json()
    # Queue for async processing -- don't block the response
    background_tasks.add_task(process_webhook, payload)
    return {"status": "received"}  # Return 200 immediately

4. Use excluded paths. In your Leadpipe dashboard, exclude pages that will never produce useful leads: /admin, /login, /careers, /support. This reduces noise and saves your identification credits for pages that matter.

5. Monitor delivery health. Leadpipe shows webhook delivery success rates in your dashboard. If your success rate drops below 95%, check your endpoint logs — you probably have a timeout or authentication issue.

6. Implement deduplication. Even with First Match, edge cases can produce near-duplicate payloads (e.g., a visitor identified across two sessions). Keep a simple cache keyed on email with a 7-day TTL.

For the full API and webhook setup walkthrough, including authentication and pixel configuration, see the quickstart guide.


FAQ

Are all fields guaranteed to be present in every payload?

Every field is included in every payload, but some may be null. The email, page_url, timestamp, and pages_viewed fields are always populated. Fields like phone, linkedin_url, and job_title depend on what Leadpipe’s identity graph has for that visitor. Expect email on 100% of payloads, job_title on ~85%, and phone on ~40-60%.

How quickly do webhooks fire after identification?

Typically within seconds. Leadpipe identifies visitors during the active session — the person doesn’t need to leave the page. This means your automation can act while the visitor is still browsing. For AI SDR workflows, this speed is the entire advantage over batch-processed contact lists.

What happens if my endpoint is down?

Leadpipe retries failed webhook deliveries automatically. If your endpoint returns a non-2xx status code or times out, the delivery will be retried with exponential backoff. You can monitor delivery status and retry history in the dashboard. That said, build your endpoint to be resilient — use a managed hosting provider with uptime guarantees (Railway, Render, AWS Lambda) rather than running on a local machine.

Can I receive webhooks for specific pages only?

Yes. Use segments in your Leadpipe dashboard to define which pages trigger webhooks. You can include specific paths (e.g., only /pricing and /demo) or exclude paths (e.g., everything under /blog). This is especially useful during testing or when you want to route different pages to different endpoints.

How does this work with the Leadpipe API?

Webhooks and the REST API are complementary. Webhooks push data to you in real-time (event-driven). The API lets you pull data on demand — query visitor histories, manage pixels programmatically, and integrate identity resolution into your SaaS platform. Most teams use webhooks for real-time actions and the API for backfill, reporting, and platform integrations.


Start Building

This reference covers every field, every trigger type, and the classification logic to turn raw payloads into pipeline. The webhook payload is the raw material. What you build on top of it — AI agents, Clay waterfalls, custom scoring models — that’s where the leverage is.

Start your free trial — 500 identified leads, no credit card required.