Hydra logoHydra · Hydra Support

Analytics & Reporting

Per-contact daily engagement strip

A 30-day bar chart above the Site Activity panel on a Lead or Contact detail page that shows whether the person has been heating up, cooling off, or steady — with an explicit "N/A" state for contacts who aren't yet linked to site tracking.

Per-contact daily engagement strip

The engagement strip is a compact 30-day bar chart that sits above the Site Activity panel on a Lead or Contact's detail page. Each bar is one day's tracked-event count for that person, color-coded by intensity, so at a glance you can tell whether they've been heating up, cooling off, or holding steady.

The strip lives on every Lead and every Contact detail page — there's no setting to turn it on. It reads from the same visitor_events stream that powers the Site Activity dashboard and the bot's visitor context, filtered to the events that have been linked to this specific person.

What the strip shows

Thirty bars across, one per day, oldest on the left and today on the right. The height of each bar is the number of tracked events on that day — pageviews, custom events, identify calls, clicks, scrolls, outbound clicks. Session-start markers are excluded from the count because they're synthetic (a session boundary, not an action), so a day with one real pageview reads as 1, not 2.

Color encodes intensity rather than a fixed scale: darker bars mean busier days relative to this contact's own range. A contact who fires hundreds of events a day and a contact who fires three are both readable at a glance — the strip is built to surface the shape of the trend, not to compare two people against each other.

Hover any bar to see the exact count and the date. The strip is paired with the Site Activity timeline directly below it — the strip is the bird's-eye view, the timeline is the row-by-row log of what actually happened. Clicking around the timeline doesn't change the strip; they're independent reads.

How the data is sourced

The strip queries GET /api/visitors/activity-summary?customer_id=<id>&days=30. The endpoint:

  • Filters to events linked to this Lead or Contact — either by customer_id directly, or by anon_visitor_id for anonymous events that have since been stitched to this record.
  • Excludes session_start events (synthetic session boundaries don't count as engagement).
  • Buckets remaining events by UTC day and zero-fills any day in the 30-day window that had no activity.

Because the bucketing is UTC, a visitor on Pacific time who hits your site at 10pm local will land in the next UTC day's bar. For most teams that's invisible. For teams analyzing very granular activity patterns it's worth knowing.

The "N/A — Not linked to site tracking" state

This is the part most worth reading carefully, because it's the state most existing contacts will be in.

When a contact has no anonymous visitor ID stitched to them and zero lifetime tracked events, the strip doesn't render thirty empty bars — it renders a single card that says "N/A — Not linked to site tracking." That's deliberate. An empty strip with thirty zero bars implies the contact was tracked and had a quiet month. "N/A" tells you the truth: nothing on your site has ever been connected to this person, so there's no shape to draw.

A contact moves out of "N/A" the moment Hydra has a way to associate their browser with their CRM record. There are two paths to that:

  1. They chat through your widget. Capturing an email through a chat flow stitches the anonymous visitor to the Lead or Contact that gets created or matched. From that moment on, anything tracked under that visitor's anonymous ID rolls up to the contact retroactively — past pageviews included.
  2. Your site code calls hydra.identify(email, ...) on a page that's also running hydra.track(...). Identify alone isn't enough — the widget has to be loaded and tracking has to be on for the page where identify fires, because identify is just another event in the same stream.

Until one of those two things happens, the contact exists in your CRM but their browser activity (if any) is sitting under an anonymous visitor ID that doesn't know who they are. The strip honestly reports "N/A" rather than guessing.

A contact who was linked but has had no activity in the last 30 days renders differently — thirty empty bars with a small "No activity in the last 30 days" caption. That's the "tracked but quiet" case, and it's a real signal (a person you used to see who's gone dark) — distinct from "we never tracked them in the first place."

Why most existing contacts will read "N/A"

The visitor-to-contact stitch is sparse on most tenants by default. A contact lands in your CRM through a lot of paths — manual entry, an import, a flow that captured them from a form, a list someone uploaded — and none of those paths involve a browser session. The browser-to-contact link only forms when the visitor actively interacts with your site through a Hydra widget and either chats or runs through identify.

So the expected pattern on day one for most tenants is:

  • New contacts who arrive via widget chat → linked from day one, strip populates immediately.
  • New contacts who arrive via an authenticated app calling hydra.identify → linked from the next page load after the identify call.
  • All other contacts (imports, manual entry, form fills without a widget, leads from outbound) → "N/A" until they happen to chat with your widget or you wire identify into the authenticated surface they log into.

If you're seeing "N/A" everywhere and that feels wrong, the question to ask is "where does this contact's browser activity get connected to their record?" In most cases the answer is "it doesn't, yet" — and the fix is either to wire hydra.identify into your authenticated app (see Site Activity tracking) or to wait for the contact to chat through the widget.

Where the strip appears

  • Contact detail page — above the Site Activity panel.
  • Lead detail page — same component, same position. The Leads page and the Contacts page reuse one underlying view, so the strip behaves identically on both.

For the rolled-up view across every contact on an account — the same shape, aggregated — see Account activity rollup.

Frequently asked questions

Why does the strip say "N/A" on a contact I know visits the site? Because the contact and their browser haven't been connected yet. Existing in the CRM and existing in visitor_events are two different things — the link only forms when the visitor chats through your widget (which captures their identity) or when your site code runs hydra.identify on a page that also has the widget loaded. Until one of those happens, the contact's visits sit under an anonymous visitor ID that doesn't yet know who they are, and the strip honestly reports "N/A."

What's the difference between "N/A" and a strip with thirty empty bars? "N/A" means the contact has zero lifetime tracked events and no anonymous visitor stitched to them — they've never been linked to your site tracking at all. Thirty empty bars means the contact is linked (so the data path works) but had no activity in the last 30 days. The first state is a wiring question; the second is a real signal that a tracked person went quiet.

Does the bot's chat reply count as an event in the strip? No. Chat messages flow through /api/chat, not the tracking pipeline. The strip counts visitor_events rows — pageviews, custom events, identify calls, clicks, scrolls, and outbound clicks. The pageview that loaded the page where the chat opened does count if tracking is on for that widget; the back-and-forth messages themselves don't.

Does today's bar always show the latest activity? The strip queries on page load. If you want the most current count, refresh the page — there's no live stream pushing updates into the chart. Today's bar is partial by definition because the day isn't over yet, so a low value mid-day doesn't mean the contact is quiet; it means the day's still in progress.

Can I change the 30-day window? Not in v1. The window is fixed at 30 days. If you need a longer or shorter view, the Site Activity dashboard supports 24h / 7d / 30d / 90d ranges across all your data; the per-contact strip is tuned specifically for the 30-day shape.

What happens to the strip if I delete the contact? The contact's visitor_events rows lose their customer_id link (ON DELETE SET NULL) but the events themselves stay under their anonymous visitor ID — your aggregate dashboard counts don't change. The strip on the deleted contact is gone with the contact. If the same visitor returns and gets stitched to a new contact later, their past activity rolls into that new contact's strip.

Is there a webhook when a contact's engagement crosses a threshold? Not as a direct webhook off the strip. The supported pattern for "alert me when a contact's activity drops" is a scheduled flow alert — it runs daily over every contact, evaluates an activity-count condition, and emails when the condition matches.