Features

Everything LocalPulse does,
by the time someone hits “contact us.”

Built for the question agencies actually ask — “did anyone from our target city just land on the contact page?” Skip past the funnels and cohort builders. Here’s the whole product, surface by surface.

Tracking

Install in under a minute. See visits in seconds.

One <script> tag per client. The snippet uses sendBeacon first and falls back to fetch + keepalive — so a visitor closing the tab on the way to the contact form doesn’t lose the visit.

  • Per-client snippet key. Each site gets its own data-client identifier; no shared pixels, no cross-tenant leakage.
  • Real IPs through proxies. Honors CF-Connecting-IP, True-Client-IP, X-Real-IP, X-Forwarded-For in that order, so Cloudflare in front doesn’t mask the visitor.
  • Dynamic CORS. Access-Control-Allow-Origin echoes the request Origin so credentialed sendBeacon requests don’t bounce.
  • Session-window grouping. A 30-minute session window extends existing rows instead of inflating the count, and Slack only pings on first detection.
snippet.js1 line · 2.3 kB · deferred
<!-- paste before </body> -->
<script
  src="https://lp.app/s/9f2a.js"
  data-client="castle-rock-fitness"
  defer
></script>
First visit appears the moment one lands verified
Local detection

Geo as a primary signal, not a filter.

Every visit is classified against your client’s configured target cities, with region as a fallback. Multi-location clients tag each visit with the specific branch it matched.

  • City beats region. Perfect city match wins; region is the fallback if no city matches across the location list.
  • matchedLocationId on every row. Stored on the Visit, so the dashboard can break Local sessions down by branch. The bundled scripts/backfill-matched-location.ts re-tags historical visits when you add a new target.
  • ISP buckets. business / isp / hosting / education / government — so a Comcast subscriber doesn’t read like a lead and an AWS bot doesn’t inflate the feed.
  • VPN-aware. iCloud Private Relay and ~20 named VPNs are flagged with a shield badge instead of being silently mis-attributed.
Targets configured
Denver, CO Castle Rock, CO Boulder, CO
Last hour
14 local / 31 total
Denver · 39.74° N, 104.99° W
Pace Plumbing · Denver
Local matchBusiness
Hover any dot to see how the classifier tagged itSlack scope · local + b2b
Visitor feed

One row per session. The whole story inside it.

Click any row. It expands inline into the full session — page journey with dwell, attribution, device, locale, ISP, identity, raw user agent. No second page, no modal.

  • Filter tabs that mirror the question. All / Businesses / Local / Identified / Today / This week. Per-location filter for multi-location clients scopes both feed and analytics.
  • Per-row badges. Local (pin), Returning (loop count), Identified (user check), VPN / Private Relay (shield) — with an explainer tooltip for the last.
  • Honest pagination. Past 10,000 visits the UI shows “10,000+” instead of walking the table — saves the database and your patience.
Live visits· castle-rock-fitness.com
Denver, COComcast Cable
LocalBusiness Identified
5 pg · 6m 41sjust now
Aurora, COVerizon FiOS
Local
2 pg · 0m 48s12s ago
Castle Rock, COLumen Business
LocalBusiness Identified Returning · 3×
9 pg · 11m 02s1m ago
Frankfurt, DEHetzner Online
Hosting
1 pg · 0m 04s3m ago
Boulder, COCenturyLink
Local Returning · 2×
3 pg · 2m 17s5m ago
Identity capture

Get a name next to the visit. No CRM hookup.

The snippet itself watches form submissions on the host site, scores each input against HTML5 type, autocomplete, and a hint string built from name + id + placeholder + aria-label + label text, then upserts identity on (clientId, visitorId).

  • Sensitive fields refused. Password, CVV, SSN, tokens and similar are skipped unconditionally — no override, not even for the agency.
  • Hint matching with priority order. Word-boundary regexes, scored — so 'first_name', 'fname', 'given-name', and a label that reads 'first name' all resolve to the same field.
  • Per-client scope. off / local / all. Most agencies set this to local for noise control; B2B teams flip it to all.
  • Upsert on (clientId, visitorId). Same visitor coming back through a different form updates the identity rather than duplicating it.
visitor’s form on pace-plumbing.com snippet.js · listening
matched · First name
matched · Last name
matched · Email
matched · Phone
matched · Company
sensitive — skipped
no identity field detected
Identity captured(visitorId · v_a12c…)
Name
Email
Phone
Company
Skipped fields
  • password — sensitive type
  • message — no identity hint
Identified · upserted on (clientId, visitorId)
Slack alerts

An alert that earns the ping.

Per-client webhook with a four-mode scope — off / local-only / all / b2b — and a block-kit payload with the six things you actually need: location, company, device, dwell, source, keyword.

  • First-visit semantics. Slack fires on first detection of a session, not on every page view. A returning visitor extends the row instead.
  • Test-fire from settings. One button in client settings pushes a sample alert to the configured webhook so you can preview the format and channel.
  • Page journey + deep link. Block-kit payload ends with a “View in LocalPulse” button that opens the visit detail directly.
#leads-castle-rock
· LocalPulse
11:42 am MT
LocalPulseAPP
New local visit · Denver, CO
Location
Denver · matched “HQ — Denver”
Company
Pace Plumbing
Device
iPhone 15 · iOS 17
On site
6m 41s · 5 pages
Source
Google · plumber denver
Keyword
plumber denver near me
Page journey
  1. /· 0:38
  2. /services/water-heater-repair· 2:11
  3. /about· 0:54
  4. /contact· 2:58
visit · v_1f8a9c
Email digests

A weekly read that doesn’t need explaining.

Designed HTML digest — daily, weekly, or monthly — with a Local highlights section that names the matched branch for multi-location clients. Everything runs on the client’s timezone, not yours.

  • Per-client schedule. Cadence, hour-of-day, day-of-week (weekly) and day-of-month (monthly) — every value honors the client’s IANA timezone.
  • Idempotent delivery. Driven by /api/cron/digest. Re-running inside the same period is a no-op; missed periods get caught up on the next tick.
  • Designed, not auto-generated. Header, headline numbers, local highlights, and a list of the named visits the client should care about — no spreadsheet attachments.
LocalPulse · Weekly digest
Castle Rock Fitness
WEEK 21 · 2026
May 18 — May 24 · MT
Local sessions
284 · +18%
Identified
41
Top source
Google · gym near me
Local highlights
  • Pace Plumbing
    Denvercontact form · 11m on site
  • Anonymous · Verizon FiOS
    Phoenixreturned 3× this week · pricing page
  • Hale & Co. Law
    Castle Rockbooked a tour · 14m on site
Per-client analytics

Charts shaped like the question.

Visits over time with a Local overlay. Top campaigns with provenance. Local-by-location breakdown for multi-location clients. Traffic sources, devices, top cities, hour-of-week heatmap of local sessions.

  • Server-side aggregation. Every aggregation runs in Postgres against indexed columns — (clientId, createdAt) and (clientId, isLocal).
  • Rollup-backed long ranges. 90d and all-time read pre-aggregated VisitDailyStat rows, so cost is O(days), not O(visits).
  • Local cities highlighted. Top-cities bar tints the matched cities so the client doesn’t have to read labels to find the leads.
Visits over time
5,142+14% wow
Apr 24May 23
All visitsLocal sessions
Reliability

Quiet pipes. Visible health.

LocalPulse runs as a managed service with rollup-backed analytics for the long ranges and a background install verifier checking every client site every six hours.

  • Rollup-backed analytics. 90-day and all-time views read pre-aggregated VisitDailyStat rows so cost is O(days), not O(visits). Dashboards stay fast at every site count.
  • Install verification. Every 6h, with a Chrome user-agent to bypass naive bot blocks. The status pill overrides to “active” whenever real visits land — so a Cloudflare block doesn’t read as “broken”.
  • Cloudflare-friendly tracking. Real visitor IP via CF-Connecting-IP, True-Client-IP, X-Real-IP and X-Forwarded-For — in that order — so a proxy in front doesn’t mask the visit.
  • Retention you can read. Raw visits roll off after 365 days, after the daily rollup has captured them. Aggregate rollups outlive the raw rows for long-range analytics.
Pipelineone pipeline · five surfaces
  • Track API
    Snippet ingestion
    ok
    real-time
  • Dashboard
    App + auth
    ok
    always-on
  • Slack delivery
    Outbound webhooks
    ok
    first-visit fires
  • Install verifier
    Background snippet check
    ok
    every 6h
  • Email digests
    Daily / weekly / monthly
    ok
    on schedule
Internal use only · public release soon

One snippet. One Slack channel. Real leads.

We’re running a closed pilot while the dashboard finishes hardening. Reach out and we’ll add you to the early-access list.