What your customer is doing right now.
Signals computes attributes such as categories viewed from each event and serves them to your app in milliseconds, in region.
What you see below is your own visit to this page, computed by Signals as you read.
Signals, about you
connectingSignals is computing your first attributes from the events this page just sent.
Every highlighted part is an attribute Signals computed from the behavioral data your browser sent during this visit. Open the Product menu above and watch the sentence change.
What the customer is viewing reaches your product too late.
Most customer data reaches your product as counts and scores, such as a propensity to purchase.
An event becomes an attribute your app reads.
We host it, or it runs in your own AWS or GCP account. Signals collects events with its own SDKs, updates what it knows within a second of each event, and answers a read in 6ms at the median and 10ms at p95, in-region.
Live from the stream, history from your warehouse
user · session · basket · listing · store
A product_view event on a pair of trail shoes arrives from your app via our SDK.
Signals validates each event against its schema on the way in, so an event that fails validation does not update the attribute.
An attribute named categories_viewed gains trail, inside the 10-minute window.
<1s from the event arriving to the attribute being current. Windowing, late events and hot keys are handled in the engine, not in your code.
Your ranker reads the attribute and reorders the shoe recommendations, in the same session.
Or a real-time trigger fires when a condition you set is met and sends it to your app or to a tool such as Braze.
- Snowflake
- BigQuery
- Databricks
- Vertex AI
- Amazon Bedrock
Attributes that describe the moment, kept current for you.
from snowplow_signals import Attribute, Event, EntityPropertylast_cart_value = Attribute(name="last_cart_value",type="double",events=[Event(name="snowplow_ecommerce_action")], aggregation="last",property=EntityProperty(vendor="com.snowplowanalytics.snowplow.ecommerce" ,name="cart",major_version=1,path="total_value",),)How often, how recently, in what sequence. Or your own function, versioned like the rest.
from snowplow_signals import Attribute, Event, EntityPropertylast_cart_value = Attribute(name="last_cart_value",type="double",events=[Event(name="snowplow_ecommerce_action")], aggregation="last",property=EntityProperty(vendor="com.snowplowanalytics.snowplow.ecommerce" ,name="cart",major_version=1,path="total_value",),)user · session · account · basket · listing · store. A profile is whatever you say it is.
Ten minutes, this session, or since the last purchase. A value drops out when its window or TTL ends.
The streaming engine keeps it current, and on publish Signals backfills it from Snowflake, BigQuery or Databricks, so a new attribute has history on day one. The dataset builder makes a point-in-time correct training set from the same definition.
Your app reads the visit as it changes.
session 7f3a · one visit
- 0:40Searches three times, opens nothing
searches_session3result_clicks_session0Your search loosens the match.Search inputs - 2:15Opens one shoe three times
product_views_session{shoe: 3}adds_session0Your offer rules show a code.Offer targeting - 4:50Adds it in two sizes
product_views_session{shoe: 3}adds_session2cart_skus_session[shoe-m, shoe-l]Your cart offers the fit guide.Fit prompts
Frequently asked questions.
We already have a feature store. Why add this?
Keep it if it serves you. A feature store starts from features and assumes the events already arrive, and a live feature is only as current as the streaming job you run into it. Signals collects the events with its own SDKs, validates them against your schemas, and updates each attribute <1s after the event arrives. Signals calls each feature an attribute, and one definition serves the live value and builds the training set.
How is this different from the profile in our CDP?
A CDP builds audiences around a person from past behavior and syncs them on its own schedule, often minutes to hours later. Signals computes what a customer is doing in this visit, keyed on whatever you choose, such as a session or a basket, and serves it to your app on request. It sits underneath the CDP rather than replacing it, and a real-time trigger can send the moments it notices to your other tools.
What happens to an attribute when we change its definition?
You publish a new version of its attribute group, and every version is kept. A service pinned to the old version keeps serving it until you retire it, so an app reading the old version does not change under you. Definitions live in the Console or in code, so a change can ship through the CI/CD you have.
Do we have to move off our warehouse?
No. Snowflake, BigQuery or Databricks stays where it is. When you publish an attribute, Signals backfills its history from the warehouse with the same definition the streaming engine runs, so the live value and the history agree. If you have no warehouse, Signals also runs streaming-only.
What if next-day data is fine for us?
Then a warehouse tool is cheaper and you should buy that instead. Signals is for the ranker, the offer or the model that has to respond while the customer is still on the page.
Start with one attribute.
Add the SDK, define one attribute, and watch it update as you browse and search your own product. The free tier runs on the real engine: no card, no sales call.