Real-time customer context

Act on live customer behaviour.

Signals tells you what your customer is doing right now so your product can respond while they are still on the page.

14 days · no card · no sales call · an attribute updating against your own traffic in the first session
Your app → Signals · requestThree steps
01Track the eventonce, in your app
trackPageView(); // browser tracker, already on this page
02Define the attributeonce, in Signals
Attribute(name="pages_last_5_min", events=["page_view"],
  aggregation="category_count", property="page_urlpath",
  period=timedelta(minutes=5))
03Read it backevery request
await signals.getServiceAttributes({
  name: "signals_site_session_service",
  attribute_key: "domain_sessionid",
  identifier: "", // your session id, once set
});
All three are real. This page tracks the event, the attribute lives in Signals, and the right side is your session, now.
Signals → your app · response● connecting
waiting for the first computed value…
Your first events are in flight through a real Snowplow pipeline. Attributes appear as the stream computes them, usually within a few seconds.
Fast enough to matter

6ms p50 · 10ms p95, in-region.

Built to scale

Runs in our cloud or yours, AWS or GCP. Scales with your traffic.

Flexible where it counts

Track a shopper, a session, a basket, a store, whatever you decide. How often, how recently, over any window. One definition, live and historical.

The problem

Your data knows. Your product doesn't.

Behaviour is collected. Nothing computes it, serves it, or flags it fast enough to act inside the session. Every personalisation project has two halves, knowing and acting. Signals does the knowing, in milliseconds, and hands it to whatever you use for acting.

The loop is too slow

"Our recommender doesn't know what the user did thirty seconds ago."

We built it, now we own it

"We built a profile API. Now two engineers maintain it forever and it pages us."

It never reaches production

"Our data scientists build features in notebooks that never make it to production."

The app is blind to the moment

"Our support agent has amnesia. It can't see the customer has been stuck on the same page for four minutes."

How it works

One event in. One answer out. Same session.

One definition runs in a streaming engine for now and a batch engine for warehouse history, so production features match what data science trained on. Managed SaaS or private deployment in AWS, GCP or Azure, identical architecture.

t = 0
Your customer acts

Views, searches, adds, abandons. The SDK you already run sends the event.

view_price · 3× in 10 minutes
t + 6ms
Signals knows

Recomputes what you defined, on the stream. One definition, live and against history.

showing_price_hesitation = true
same page
Your product responds

Reads it mid-render, or a trigger pushes it wherever acts on it.

Ranker moves value options up
01 · the customer actsIllustrative. Your product decides; Signals supplies what this session has been doing.
Get started

Create your first live attribute today.

The short way

Add the Signals plugin or MCP server. Run one prompt.

Claude Code, Cursor or any MCP client. The agent adds the SDK, defines the attribute and wires the read into your app.

1 · Add
$ claude mcp add snowplow-signals -- npx @snowplow/signals-mcp
2 · Run this prompt
> Add Snowplow Signals to this app. Track product views, define showing_price_hesitation as 3+ view_price events in 10 minutes keyed on user_id, and read it back before the ranker runs.

See an attribute updating against your own traffic in the first session.

14 days. no card, no sales call. Add the SDK, define one attribute, watch it change while you click around your own product.

Talk to an engineer means an engineer: architecture, latency boundary, failure modes, how it runs in your cloud. Not a demo script.