From 09eb9b869e48b2228e2dbb924830617859c227c5 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Tue, 15 Jul 2025 13:32:10 +0100 Subject: [PATCH 01/11] Tidy up the metadata --- tutorials/signals-quickstart/meta.json | 4 ++-- tutorials/snowplow-batch-engine/meta.json | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tutorials/signals-quickstart/meta.json b/tutorials/signals-quickstart/meta.json index ffdf9a5b04..0e18e656dd 100644 --- a/tutorials/signals-quickstart/meta.json +++ b/tutorials/signals-quickstart/meta.json @@ -1,5 +1,5 @@ { - "title": "Signals Quick Start", - "description": "Set up Signals to calculate attributes in real time.", + "title": "Set up Signals for real-time calculation", + "description": "Set up Signals to calculate attributes in near real time.", "label": "Signals" } diff --git a/tutorials/snowplow-batch-engine/meta.json b/tutorials/snowplow-batch-engine/meta.json index 946cde814d..f9e0c7d24a 100644 --- a/tutorials/snowplow-batch-engine/meta.json +++ b/tutorials/snowplow-batch-engine/meta.json @@ -1,5 +1,5 @@ { - "title": "Snowplow Signals Batch Engine Tutorial", - "description": "Learn how to use the Snowplow Signals SDK CLI tool to manage dbt projects and generate data models", - "label": "Solution accelerator" + "title": "Set up the Signals batch engine", + "description": "Use the Signals batch engine CLI tool to calculate attributes from your warehouse data.", + "label": "Signals" } From 59ab8097c54066aa4f3b8c7788ef841c8cd9b884 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Tue, 15 Jul 2025 15:03:15 +0100 Subject: [PATCH 02/11] Add stub pages --- tutorials/signals-quickstart/colab.md | 6 ++++ tutorials/signals-quickstart/conclusion.md | 6 ++++ tutorials/signals-quickstart/define-view.md | 2 +- tutorials/signals-quickstart/deploy.md | 12 +++++++ tutorials/signals-quickstart/start.md | 12 ++++++- tutorials/snowplow-batch-engine/conclusion.md | 6 ++++ tutorials/snowplow-batch-engine/install.md | 28 +++++++++++++++++ tutorials/snowplow-batch-engine/start.md | 31 ++----------------- 8 files changed, 72 insertions(+), 31 deletions(-) create mode 100644 tutorials/signals-quickstart/colab.md create mode 100644 tutorials/signals-quickstart/conclusion.md create mode 100644 tutorials/signals-quickstart/deploy.md create mode 100644 tutorials/snowplow-batch-engine/conclusion.md create mode 100644 tutorials/snowplow-batch-engine/install.md diff --git a/tutorials/signals-quickstart/colab.md b/tutorials/signals-quickstart/colab.md new file mode 100644 index 0000000000..c147e8586d --- /dev/null +++ b/tutorials/signals-quickstart/colab.md @@ -0,0 +1,6 @@ +--- +position: 1.5 +title: Interactive tutorial with Colab +--- + +You can try an interactive version of this Quickstart on Google Colab [here](https://colab.research.google.com/drive/1ExqheS4lIuJRs0wk0B6sxaYfnZGcTYUv). diff --git a/tutorials/signals-quickstart/conclusion.md b/tutorials/signals-quickstart/conclusion.md new file mode 100644 index 0000000000..2bcc16a716 --- /dev/null +++ b/tutorials/signals-quickstart/conclusion.md @@ -0,0 +1,6 @@ +--- +position: 10 +title: Conclusion +--- + +TODO diff --git a/tutorials/signals-quickstart/define-view.md b/tutorials/signals-quickstart/define-view.md index ae20ec60a0..a57ff5ee3c 100644 --- a/tutorials/signals-quickstart/define-view.md +++ b/tutorials/signals-quickstart/define-view.md @@ -1,6 +1,6 @@ --- position: 4 -title: Create and deploy a view +title: Create and test a view --- A `View` is a collection of attributes that share a common entity (e.g., session or user). Here's how to create a view with the attributes we defined earlier: diff --git a/tutorials/signals-quickstart/deploy.md b/tutorials/signals-quickstart/deploy.md new file mode 100644 index 0000000000..c26de3d94d --- /dev/null +++ b/tutorials/signals-quickstart/deploy.md @@ -0,0 +1,12 @@ +--- +position: 4.5 +title: Deploy configuration +--- + +Once you're satisfied with the view, deploy it to the API using the `apply` method: + +```python +sp_signals.apply([my_attribute_view]) +``` + +This makes the view live, and events will start being processed based on the defined attributes. diff --git a/tutorials/signals-quickstart/start.md b/tutorials/signals-quickstart/start.md index 574ae5a2e7..037c2235c8 100644 --- a/tutorials/signals-quickstart/start.md +++ b/tutorials/signals-quickstart/start.md @@ -1,6 +1,6 @@ --- position: 1 -title: Getting Started with Signals +title: Introduction --- :::note @@ -17,3 +17,13 @@ Welcome to the Snowplow Signals Quickstart! This guide will walk you through the 5. **Retrieve Attributes**: Fetch user features from the Profile API. Steps 1-4 are the Signals configuration. Step 5 shows how to start using the stored attributes. + +## Prerequisites + +Before starting, ensure you have: + +- Python 3.11+ installed + + + +## What you'll learn diff --git a/tutorials/snowplow-batch-engine/conclusion.md b/tutorials/snowplow-batch-engine/conclusion.md new file mode 100644 index 0000000000..2bcc16a716 --- /dev/null +++ b/tutorials/snowplow-batch-engine/conclusion.md @@ -0,0 +1,6 @@ +--- +position: 10 +title: Conclusion +--- + +TODO diff --git a/tutorials/snowplow-batch-engine/install.md b/tutorials/snowplow-batch-engine/install.md new file mode 100644 index 0000000000..6297f5d96f --- /dev/null +++ b/tutorials/snowplow-batch-engine/install.md @@ -0,0 +1,28 @@ +--- +position: 1.5 +title: Install the CLI +--- + +To install the Signals Batch Engine CLI tool, run the following command: + +```bash +pip install 'snowplow-signals[batch-engine]' +``` + +This will install the CLI tool along with all necessary dependencies for working with batch views. + +**Important**: Make sure you're in the correct Python environment (virtual environment, Poetry, etc.) where you want to install the CLI tool. The CLI commands will only work in the environment where the package is installed. + +## Setting Up Environment Variables + +To make your workflow smoother, you can set up your API credentials as environment variables. This way, you won't need to type them in every command: + +```bash +export SNOWPLOW_API_URL="YOUR_API_URL" +export SNOWPLOW_API_KEY="YOUR_API_KEY" +export SNOWPLOW_API_KEY_ID="YOUR_API_KEY_ID" +export SNOWPLOW_ORG_ID="YOUR_ORG_ID" +export SNOWPLOW_REPO_PATH="./my_snowplow_repo" +``` + +Ready to begin? Let's start by testing your connection to the Snowplow Signals services. diff --git a/tutorials/snowplow-batch-engine/start.md b/tutorials/snowplow-batch-engine/start.md index d35459d917..ae890bf69c 100644 --- a/tutorials/snowplow-batch-engine/start.md +++ b/tutorials/snowplow-batch-engine/start.md @@ -1,6 +1,6 @@ --- position: 1 -title: Getting Started with Signals Batch Engine +title: Introduction --- Welcome to the Signals Batch Engine guide! This tool helps you generate and manage dbt projects for batch processing of your Snowplow Signals attributes. @@ -31,23 +31,10 @@ Before starting, ensure you have: - Organization ID - Have View(s) already created -:::info +:::info Make sure you specified `offline = True` in your View definition. ::: - -## Installation - -To install the Signals Batch Engine CLI tool, run the following command: - -```bash -pip install 'snowplow-signals[batch-engine]' -``` - -This will install the CLI tool along with all necessary dependencies for working with batch views. - -> **Important**: Make sure you're in the correct Python environment (virtual environment, Poetry, etc.) where you want to install the CLI tool. The CLI commands will only work in the environment where the package is installed. - ## What you'll learn This tutorial will guide you through the complete process of working with batch views in Snowplow Signals: @@ -58,17 +45,3 @@ This tutorial will guide you through the complete process of working with batch 4. Generating data models automatically 5. Running and testing your models 6. Materializing your models to the feature store - -## Setting Up Environment Variables - -To make your workflow smoother, you can set up your API credentials as environment variables. This way, you won't need to type them in every command: - -```bash -export SNOWPLOW_API_URL="YOUR_API_URL" -export SNOWPLOW_API_KEY="YOUR_API_KEY" -export SNOWPLOW_API_KEY_ID="YOUR_API_KEY_ID" -export SNOWPLOW_ORG_ID="YOUR_ORG_ID" -export SNOWPLOW_REPO_PATH="./my_snowplow_repo" -``` - -Ready to begin? Let's start by testing your connection to the Snowplow Signals services. From f3555c55adbe9a1f5ae44119122855465c2d1881 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Tue, 15 Jul 2025 18:42:45 +0100 Subject: [PATCH 03/11] Add example attributes --- .../signals/configuration/attributes/index.md | 1 + tutorials/signals-quickstart/conclusion.md | 4 + .../signals-quickstart/define-attribute.md | 102 +++++++++++++++--- tutorials/signals-quickstart/install.md | 46 +++++--- .../{colab.md => interactive-colab.md} | 2 +- tutorials/signals-quickstart/start.md | 8 ++ .../{define-view.md => test-view.md} | 17 +-- 7 files changed, 133 insertions(+), 47 deletions(-) rename tutorials/signals-quickstart/{colab.md => interactive-colab.md} (81%) rename tutorials/signals-quickstart/{define-view.md => test-view.md} (70%) diff --git a/docs/signals/configuration/attributes/index.md b/docs/signals/configuration/attributes/index.md index 87eb4457bf..a8e3da64e7 100644 --- a/docs/signals/configuration/attributes/index.md +++ b/docs/signals/configuration/attributes/index.md @@ -174,6 +174,7 @@ This example extends the previous minimal example. Now the attribute is only cal ```python from snowplow_signals import Attribute, Event, Criteria, Criterion +from datetime import timedelta my_attribute = Attribute( name="emoji_button_click_counter", diff --git a/tutorials/signals-quickstart/conclusion.md b/tutorials/signals-quickstart/conclusion.md index 2bcc16a716..cec6e25c52 100644 --- a/tutorials/signals-quickstart/conclusion.md +++ b/tutorials/signals-quickstart/conclusion.md @@ -4,3 +4,7 @@ title: Conclusion --- TODO + + +next steps: +play with other entities? diff --git a/tutorials/signals-quickstart/define-attribute.md b/tutorials/signals-quickstart/define-attribute.md index d4e599d196..0f7ed18400 100644 --- a/tutorials/signals-quickstart/define-attribute.md +++ b/tutorials/signals-quickstart/define-attribute.md @@ -1,15 +1,25 @@ --- position: 3 -title: Define an attribute +title: Define and group attributes --- -An `Attribute` represents a specific fact about a user's behavior. For example, you can define an attribute to count the number of `page_view` events a user has made. +An `Attribute` describes a specific fact about user behavior. They're grouped into `View`s for management and deployment. + +In this tutorial you will define three attributes based on page view events. + +## Define attributes + +### Page view counter + +The first attribute counts the number of page view events within the last 5 minutes. It uses the `counter` aggregation. The time window is defined by the `period` parameter. ```python from snowplow_signals import Attribute, Event +from datetime import timedelta page_view_count = Attribute( name="page_view_count", + description="Page views in the last 5 minutes.", type="int32", events=[ Event( @@ -19,33 +29,91 @@ page_view_count = Attribute( ) ], aggregation="counter" + period=timedelta(minutes=5), ) ``` -You can refine to your attributes by adding `Criteria` to filter for specific events. For example: + +### Most recent browser + +The second attribute stores the last seen browser name (e.g. "Safari"), using the `last` aggregation. The `property` tells Signals where to look in the event for the value. Browser information is parsed from an event by the YAUAA enrichment, and appended to the event as an YAUAA entity ADD LINK. Within this entity, the browser name is stored in the `agentName` property. ```python -from snowplow_signals import Attribute, Event, Criteria, Criterion +from snowplow_signals import Attribute, Event -products_added_to_cart_feature = Attribute( - name="products_added_to_cart", - type="string_list", +most_recent_browser = Attribute( + name="most_recent_browser", + description="The last browser name tracked.", + type="string", events=[ Event( - vendor="com.snowplowanalytics.snowplow.ecommerce", - name="snowplow_ecommerce_action", - version="1-0-2", + vendor="com.snowplowanalytics.snowplow", + name="page_view", + version="1-0-0", ) ], - aggregation="unique_list", - property="contexts_com_snowplowanalytics_snowplow_ecommerce_product_1[0].name", + aggregation="last", + property="contexts_nl_basjes_yauaa_context_1[0].agentName", +) +``` + +### First referrer + +The third attribute stores the first seen referrer path, based on the `refr_urlhost` event property ADD LINK and the `first` aggregation. By using a `criteria` filter, it's only calculated for page views with a non-empty referrer ADD LINK. + +```python +first_referrer = Attribute( + name="first_referrer", + description="The first referrer tracked.", + type="string", + events=[ + Event( + vendor="com.snowplowanalytics.snowplow", + name="page_view", + version="1-0-0", + ) + ], + aggregation="first", + property="refr_urlhost", criteria=Criteria( all=[ Criterion( - property="unstruct_event_com_snowplowanalytics_snowplow_ecommerce_snowplow_ecommerce_action_1:type", - operator="=", - value="add_to_cart", - ), - ], + property="page_referrer", + operator="!=", + value="" + ) + ] ), + default_value=None ) ``` + +Add all three attribute definitions to your notebook, and run the cell. + +## Define a view + +Single attribute definitions can't be deployed to Signals, as they don't make sense without the additional context defined in a `View`. + +Group the attributes together, adding the session entity identifier `domain_sessionid`. + +```python +from snowplow_signals import View, domain_sessionid + +my_attribute_view = View( + name="my_attribute_view", + version=1, + entity=domain_sessionid, + owner="user@company.com", + attributes=[ + page_view_count, + most_recent_browser, + first_referrer + ], +) +``` + +Because of the session entity, Signals will calculate these attributes as follows: +* How many page views in the last 5 minutes for each session +* The last seen browser name for each session +* The first seen referrer for each session + +Add this view definition to your notebook, and run the cell. diff --git a/tutorials/signals-quickstart/install.md b/tutorials/signals-quickstart/install.md index 89418efd5b..a0027f2818 100644 --- a/tutorials/signals-quickstart/install.md +++ b/tutorials/signals-quickstart/install.md @@ -1,30 +1,50 @@ --- position: 2 -title: Installation +title: Install the SDK --- -The Snowplow Signals SDK allows you to define attributes, create views, and retrieve user features. It requires Python 3.12 or above. +Choose where to store your Signals configurations. We recommend creating a new repository. -Install the SDK using pip: +The easiest way to use the Python SDK is within a Jupyter notebook. + +## Install the Python SDK + +Within your notebook, install the SDK. ```bash -$ pip install snowplow-signals +pip install snowplow-signals ``` -To connect to your Signals deployment, you will need 4 values: +Once installed, you can start to define your configuration components. To test or apply your configuration, or retrieve calculated attributes from the Profiles Store, you'll need to connect to your Signals deployment. + +## Connect to Signals + +To connect to Signals, you will need 4 values: + +| Value | Description | Where to get it | Format | +| --------------- | --------------------------------------- | ------------------------------- | --------------------------------- | +| Signals API URL | The API URL for your Signals deployment | Provided by Snowplow | `https://{{UUID}}.svc.snplow.net` | +| API key | A Snowplow API key | Generated by you in BDP Console | UUID | +| API key ID | A Snowplow API key ID | Generated by you in BDP Console | UUID | +| Organization ID | Your Snowplow organization ID | Part of your BDP Console URL | UUID | -- API URL - This will be generated by Snowplow and shared with you -- API Key ID and the corresponding API Key (secret), which are generated from the [credentials section](https://console.snowplowanalytics.com/credentials) in BDP Console. -- The organization ID, which can be retrieved from the URL immediately following the .com when visiting BDP Console: +This image shows how to find your organization ID: -![](./images/orgID.png) +![A screenshot of a BDP Console URL, with the org ID highlighted](./images/orgID.png) + +Follow the instructions in [Account management](/docs/account-management/) to generate your API key and key ID. + +Add these four tokens to your environment or notebook secrets. + +Create a `Signals` object by passing in the required values. This example shows how to access notebook secrets, assuming you gave them these names: ```python from snowplow_signals import Signals + sp_signals = Signals( - api_url="https://example.svc.snplow.net/", - api_key="abcd1234", - api_key_id="1234-abcd", - org_id="48hs23js-31b3-3840-bh23-r7j23845", + api_url=userdata.get('SP_API_URL'), + api_key=userdata.get('SP_API_KEY'), + api_key_id=userdata.get('SP_API_KEY_ID'), + org_id=userdata.get('SP_ORG_ID'), ) ``` diff --git a/tutorials/signals-quickstart/colab.md b/tutorials/signals-quickstart/interactive-colab.md similarity index 81% rename from tutorials/signals-quickstart/colab.md rename to tutorials/signals-quickstart/interactive-colab.md index c147e8586d..e94605b2a1 100644 --- a/tutorials/signals-quickstart/colab.md +++ b/tutorials/signals-quickstart/interactive-colab.md @@ -1,6 +1,6 @@ --- position: 1.5 -title: Interactive tutorial with Colab +title: Interactive version --- You can try an interactive version of this Quickstart on Google Colab [here](https://colab.research.google.com/drive/1ExqheS4lIuJRs0wk0B6sxaYfnZGcTYUv). diff --git a/tutorials/signals-quickstart/start.md b/tutorials/signals-quickstart/start.md index 037c2235c8..f92237b839 100644 --- a/tutorials/signals-quickstart/start.md +++ b/tutorials/signals-quickstart/start.md @@ -25,5 +25,13 @@ Before starting, ensure you have: - Python 3.11+ installed +assumes notebook knowledge - link to basic tutorial? + + +TODO you'll need events?! +web tracker, page views, YAUAA - installed by default, referrer parser - installed by default + + +The Snowplow Signals SDK allows you to define attributes, create views, and retrieve user features. It requires Python 3.12 or above. ## What you'll learn diff --git a/tutorials/signals-quickstart/define-view.md b/tutorials/signals-quickstart/test-view.md similarity index 70% rename from tutorials/signals-quickstart/define-view.md rename to tutorials/signals-quickstart/test-view.md index a57ff5ee3c..32557bbb75 100644 --- a/tutorials/signals-quickstart/define-view.md +++ b/tutorials/signals-quickstart/test-view.md @@ -1,24 +1,9 @@ --- position: 4 -title: Create and test a view +title: Test the definitions --- -A `View` is a collection of attributes that share a common entity (e.g., session or user). Here's how to create a view with the attributes we defined earlier: -```python -from snowplow_signals import View, domain_sessionid - -my_attribute_view = View( - name="my_attribute_view", - version=1, - entity=domain_sessionid, - attributes=[ - page_view_count, - products_added_to_cart_feature, - ], - owner="user@company.com", -) -``` Before deploying the view, you can test it on the atomic events table from the past hour: From 4588d8d955c59c40ef90c4e0717513500e388aba Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Wed, 16 Jul 2025 15:08:57 +0100 Subject: [PATCH 04/11] Add intro etc --- tutorials/signals-quickstart/conclusion.md | 16 ++++- .../signals-quickstart/define-attribute.md | 20 ++++-- tutorials/signals-quickstart/deploy.md | 8 ++- tutorials/signals-quickstart/images/orgID.png | Bin 19006 -> 0 bytes tutorials/signals-quickstart/install.md | 31 +++------ .../signals-quickstart/interactive-colab.md | 6 -- .../signals-quickstart/retrieve-attributes.md | 31 ++++++--- tutorials/signals-quickstart/start.md | 39 +++++------ tutorials/signals-quickstart/test-view.md | 63 +++++++++++++----- 9 files changed, 131 insertions(+), 83 deletions(-) delete mode 100644 tutorials/signals-quickstart/images/orgID.png delete mode 100644 tutorials/signals-quickstart/interactive-colab.md diff --git a/tutorials/signals-quickstart/conclusion.md b/tutorials/signals-quickstart/conclusion.md index cec6e25c52..84a647c12d 100644 --- a/tutorials/signals-quickstart/conclusion.md +++ b/tutorials/signals-quickstart/conclusion.md @@ -3,8 +3,18 @@ position: 10 title: Conclusion --- -TODO +In this tutorial you've learned how to use Signals to calculate and serve information about user behavior in near real time. +This is the process workflow: +* Define attributes +* Test definitions +* Apply attribute configurations to Signals +* Retrieve calculated attribute values from the Profiles Store -next steps: -play with other entities? +## Next steps + +Here are some ideas for further exploration: +* Try out other entities, e.g. `domain_userid`, to calculate the attributes against +* Define attributes based off other event types +* Retrieve calculated attributes in your real applications +* Explore our other Signals tutorials diff --git a/tutorials/signals-quickstart/define-attribute.md b/tutorials/signals-quickstart/define-attribute.md index 0f7ed18400..e3be15c197 100644 --- a/tutorials/signals-quickstart/define-attribute.md +++ b/tutorials/signals-quickstart/define-attribute.md @@ -5,10 +5,10 @@ title: Define and group attributes An `Attribute` describes a specific fact about user behavior. They're grouped into `View`s for management and deployment. -In this tutorial you will define three attributes based on page view events. - ## Define attributes +In this tutorial you will define three attributes based on page view events. + ### Page view counter The first attribute counts the number of page view events within the last 5 minutes. It uses the `counter` aggregation. The time window is defined by the `period` parameter. @@ -33,12 +33,19 @@ page_view_count = Attribute( ) ``` +Note that there's an 100 event limit for time-windowed [event processing in stream](/docs/signals/configuration/stream-calculations). + ### Most recent browser -The second attribute stores the last seen browser name (e.g. "Safari"), using the `last` aggregation. The `property` tells Signals where to look in the event for the value. Browser information is parsed from an event by the YAUAA enrichment, and appended to the event as an YAUAA entity ADD LINK. Within this entity, the browser name is stored in the `agentName` property. +The second attribute stores the last seen browser name (e.g. "Safari"), using the `last` aggregation. The `property` tells Signals where to look in the event for the value. + +Browser information is appended to every event by the [YAUAA enrichment](/docs/pipeline/enrichments/available-enrichments/yauaa-enrichment/) as an entity with schema URI `iglu:nl.basjes/yauaa_context/jsonschema/1-0-1`. Within the event payload, this URI becomes `contexts_nl_basjes_yauaa_context_1`. The `property` defined in this attribute uses the `agentName` field from the YAUAA entity. Note the `[0]` index to access the entity data. + +In general, your attribute `property` definitions will be based on a column or field from the event, with the column name as seen in your warehouse. ```python from snowplow_signals import Attribute, Event +from datetime import timedelta most_recent_browser = Attribute( name="most_recent_browser", @@ -58,9 +65,12 @@ most_recent_browser = Attribute( ### First referrer -The third attribute stores the first seen referrer path, based on the `refr_urlhost` event property ADD LINK and the `first` aggregation. By using a `criteria` filter, it's only calculated for page views with a non-empty referrer ADD LINK. +The third attribute stores the first seen referrer path, based on the `refr_urlhost` [atomic event property](/docs/fundamentals/canonical-event/#platform-specific-fields) and the `first` aggregation. By using a `criteria` filter, it's only calculated for page views where the referrer isn't an empty string. ```python +from snowplow_signals import Attribute, Event, Criteria, Criterion +from datetime import timedelta + first_referrer = Attribute( name="first_referrer", description="The first referrer tracked.", @@ -98,7 +108,7 @@ Group the attributes together, adding the session entity identifier `domain_sess ```python from snowplow_signals import View, domain_sessionid -my_attribute_view = View( +my_view = View( name="my_attribute_view", version=1, entity=domain_sessionid, diff --git a/tutorials/signals-quickstart/deploy.md b/tutorials/signals-quickstart/deploy.md index c26de3d94d..ef673027e3 100644 --- a/tutorials/signals-quickstart/deploy.md +++ b/tutorials/signals-quickstart/deploy.md @@ -3,10 +3,12 @@ position: 4.5 title: Deploy configuration --- -Once you're satisfied with the view, deploy it to the API using the `apply` method: +Once you're satisfied with the definitions, deploy them to the Signals API using the `apply` method: ```python -sp_signals.apply([my_attribute_view]) +sp_signals.apply( + [my_view] +) ``` -This makes the view live, and events will start being processed based on the defined attributes. +The view is now live. Signals will start processing events in your real-time stream, and computing attributes. diff --git a/tutorials/signals-quickstart/images/orgID.png b/tutorials/signals-quickstart/images/orgID.png deleted file mode 100644 index 51a470f5b5f376fc589eb6e89b81a586abddb12a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19006 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 diff --git a/tutorials/signals-quickstart/install.md b/tutorials/signals-quickstart/install.md index a0027f2818..38ddfa380b 100644 --- a/tutorials/signals-quickstart/install.md +++ b/tutorials/signals-quickstart/install.md @@ -1,40 +1,31 @@ --- position: 2 -title: Install the SDK +title: Install and connect to Signals --- Choose where to store your Signals configurations. We recommend creating a new repository. -The easiest way to use the Python SDK is within a Jupyter notebook. - ## Install the Python SDK -Within your notebook, install the SDK. +The easiest way to use the Python SDK is within a Jupyter notebook. + +Create a new notebook in your repo. Add this code: ```bash pip install snowplow-signals ``` -Once installed, you can start to define your configuration components. To test or apply your configuration, or retrieve calculated attributes from the Profiles Store, you'll need to connect to your Signals deployment. +Run this cell to install the SDK. ## Connect to Signals -To connect to Signals, you will need 4 values: - -| Value | Description | Where to get it | Format | -| --------------- | --------------------------------------- | ------------------------------- | --------------------------------- | -| Signals API URL | The API URL for your Signals deployment | Provided by Snowplow | `https://{{UUID}}.svc.snplow.net` | -| API key | A Snowplow API key | Generated by you in BDP Console | UUID | -| API key ID | A Snowplow API key ID | Generated by you in BDP Console | UUID | -| Organization ID | Your Snowplow organization ID | Part of your BDP Console URL | UUID | - -This image shows how to find your organization ID: - -![A screenshot of a BDP Console URL, with the org ID highlighted](./images/orgID.png) - -Follow the instructions in [Account management](/docs/account-management/) to generate your API key and key ID. +The next step is to connect to your Signals deployment. You'll need this connection to test or apply your configuration, or retrieve calculated attributes from the Profiles Store. -Add these four tokens to your environment or notebook secrets. +Add your four connection tokens to the notebook secrets: + * Signals API URL + * API key + * API key ID + * Organization ID Create a `Signals` object by passing in the required values. This example shows how to access notebook secrets, assuming you gave them these names: diff --git a/tutorials/signals-quickstart/interactive-colab.md b/tutorials/signals-quickstart/interactive-colab.md deleted file mode 100644 index e94605b2a1..0000000000 --- a/tutorials/signals-quickstart/interactive-colab.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -position: 1.5 -title: Interactive version ---- - -You can try an interactive version of this Quickstart on Google Colab [here](https://colab.research.google.com/drive/1ExqheS4lIuJRs0wk0B6sxaYfnZGcTYUv). diff --git a/tutorials/signals-quickstart/retrieve-attributes.md b/tutorials/signals-quickstart/retrieve-attributes.md index f04353a225..beb5fd7a72 100644 --- a/tutorials/signals-quickstart/retrieve-attributes.md +++ b/tutorials/signals-quickstart/retrieve-attributes.md @@ -1,19 +1,34 @@ --- position: 5 -title: Retrieve attributes +title: Retrieve calculated attributes --- -Now that events are being processed, you can retrieve user features from the API: +For a real use case, you'll want to retrieve calculated attributes into your applications. + +You can use the Python SDK and Node.js SDKs to retrieve attributes from the Profiles Store, or the Signals API directly. Read about these options [in the Signals documentation](/docs/signals/retrieval/). + +For this tutorial, you'll retrieve attributes into your notebook. Add a new cell for getting values. + +Unlike when testing views, which returns multiple random entities, when retrieving calculated attributes you have to specify an entity instance. + +Pass in the name of the view, and the specific entity identifiers of interest. This example shows a `domain_sessionid` taken from the earlier test results table: ```python response = sp_signals.get_online_attributes( - source=my_attribute_view, - identifiers="abc-123", + source=my_view, + identifiers=["d99f6db1-7b28-46ca-a3ef-f0aace99ed86"] ) + +df=response.to_dataframe() +df ``` -Expected Output +In your real application, you can access the current session ID and use it to retrieve the relevant attribute values. The attributes are being calculated in near real time, in session. + +In this tutorial example, it's harder to access anything interesting, as you might not know what sessions are active. + +| | `domain_sessionid` | `page_view_count` | `most_recent_browser` | `first_referrer_path` | +| --- | -------------------------------------- | ----------------- | --------------------- | --------------------- | +| 0 | `d99f6db1-7b28-46ca-a3ef-f0aace99ed86` | None | None | None | -| **domain_sessionid** | **page_view_count** | **products_added_to_cart** | -| -------------------- | ------------------- | -------------------------- | -| abc-123 | 3 | [`blue_shoes`] | +Read about how to access IDs such as `domain_sessionid` in your web application in [Getting cookie information](/docs/sources/trackers/web-trackers/cookies-and-local-storage/getting-cookie-values/#getdomainuserid). diff --git a/tutorials/signals-quickstart/start.md b/tutorials/signals-quickstart/start.md index f92237b839..8d21c28ffa 100644 --- a/tutorials/signals-quickstart/start.md +++ b/tutorials/signals-quickstart/start.md @@ -3,35 +3,30 @@ position: 1 title: Introduction --- -:::note -You can try an interactive version of this Quickstart on Google Colab [here](https://colab.research.google.com/drive/1ExqheS4lIuJRs0wk0B6sxaYfnZGcTYUv). -::: +Welcome to the [Snowplow Signals](/docs/signals/) Quick Start tutorial. +Snowplow Signals is a real-time personalization engine for customer intelligence, built on Snowplow's behavioral data pipeline. It allows you to compute, access, and act on in-session stream and historical user data, in near real time. -Welcome to the Snowplow Signals Quickstart! This guide will walk you through the steps to set up and use Snowplow Signals to define attributes, create views, and retrieve user features. By the end of this guide, you'll have a working setup to personalize your applications using Snowplow Signals. - -1. **Install and Set Up the SDK**: Get started with the Snowplow Signals SDK. -2. **Define an Attribute**: Learn how to define stream user behavior attributes. -3. **Create and Test a View**: Combine attributes into a view and test it. -4. **Deploy a View**: Push a view to the Profile API -5. **Retrieve Attributes**: Fetch user features from the Profile API. - -Steps 1-4 are the Signals configuration. Step 5 shows how to start using the stored attributes. +This guide will walk you through the steps to calculate user behavior attributes from your Snowplow event stream, and retrieve them for use in your application. This will unlock real-time personalization use cases for your business. ## Prerequisites -Before starting, ensure you have: - -- Python 3.11+ installed - - -assumes notebook knowledge - link to basic tutorial? +This tutorial assumes that you have: +* Python 3.12+ installed in your environment +* Basic Python and [Jupyter notebook](https://jupyter.org/) knowledge +* Deployed Snowplow page view tracking from a web application +* Snowflake warehouse +* Valid API credentials for your Signals account: + * Signals API URL + * Snowplow API key + * Snowplow API key ID + * Snowplow organization ID -TODO you'll need events?! -web tracker, page views, YAUAA - installed by default, referrer parser - installed by default +Check out the [Signals configuration](/docs/signals/configuration) documentation to find out how to generate these credentials. +## Interactive version -The Snowplow Signals SDK allows you to define attributes, create views, and retrieve user features. It requires Python 3.12 or above. +Try out an interactive version of this tutorial on Google Colab [here](https://colab.research.google.com/drive/1ExqheS4lIuJRs0wk0B6sxaYfnZGcTYUv). -## What you'll learn +You'll need to log in with a Google account to use the Colab notebook. diff --git a/tutorials/signals-quickstart/test-view.md b/tutorials/signals-quickstart/test-view.md index 32557bbb75..f577f3d45a 100644 --- a/tutorials/signals-quickstart/test-view.md +++ b/tutorials/signals-quickstart/test-view.md @@ -3,36 +3,67 @@ position: 4 title: Test the definitions --- +Signals will start processing events and computing attributes as soon as you apply the view configuration. +It's a good idea to test the definitions before deployment. -Before deploying the view, you can test it on the atomic events table from the past hour: - +Add a new cell to your notebook with the following code: ```python data = sp_signals.test( - view=view, - app_ids=["website"], + view=my_view ) print(data) ``` -Example Output +Running this will calculate the attributes from your atomic events table. By default, events from the last hour are considered. + +You should see something like this: + +| | `domain_sessionid` | `page_view_count` | `most_recent_browser` | `first_referrer_path` | +| --- | -------------------------------------- | ----------------- | --------------------- | --------------------- | +| 0 | `d99f6db1-7b28-46ca-a3ef-f0aace99ed86` | 0 | "Firefox" | None | +| 1 | `08d833ec-5eef-461c-b452-842e7bd27067` | 1 | "Chrome" | "www.google.com" | +| 2 | `c4311466-231a-41ca-89d8-f2ff85e62a29` | 0 | "Chrome" | "duckduckgo.com" | +| 3 | `23937e09-b640-447e-82d9-c01bc16decb2` | 0 | "Chrome" | "www.google.com" | +| 4 | `61fb46c9-bfd3-48cd-a991-7a8484d1de8c` | 0 | None | None | +| 5 | `b0625a55-8382-4bfb-be9f-fefd75ad7e63` | 1 | "Chrome" | None | +| 6 | `d97140c3-3c5e-426e-8527-15314efb2be3` | 0 | "Chrome" | None | +| 7 | `4da52032-f6d1-41b4-9cf2-b40e164cbe6e` | 1 | "Chrome" | None | +| 8 | `2ee80a4a-86dd-4a24-b697-0709b29ed079` | 0 | "Safari" | None | + +The test method returns the most recent 10 rows. The first column shows the entity values, in this case for the session entity `domain_sessionid`. -| **domain_sessionid** | **page_view_count** | **products_added_to_cart** | -| -------------------- | ------------------- | -------------------------- | -| xyz | 5 | [`red_hat`, `blue_shoes`] | -| abc | 3 | [`green_trainers`] | +The attributes look as expected, so the view is ready to deploy. -:::warning -**Note:** You can filter on specific app_ids during testing. To avoid unnecessary compute, the streaming engine is typically configured to process only a subset of relevant app_ids. While you may be able to test using any app_id, bear in mind that data retrieval might not return expected results if that app_id isn't included in the streaming engine’s configuration. -::: +## Testing for individual entities -## Deploy the view +You can also test specific entity instances, by providing a list of IDs. -Once you're satisfied with the View, deploy it to the API using the `apply` method: +This example will be calculated for just these two `domain_sessionid`s: ```python -sp_signals.apply([my_attribute_view]) +data = sp_signals.test( + view=my_view, + entity_ids=["d99f6db1-7b28-46ca-a3ef-f0aace99ed86", "08d833ec-5eef-461c-b452-842e7bd27067"] +) +``` + +| | `domain_sessionid` | `page_view_count` | `most_recent_browser` | `first_referrer_path` | +| --- | -------------------------------------- | ----------------- | --------------------- | --------------------- | +| 0 | `d99f6db1-7b28-46ca-a3ef-f0aace99ed86` | 0 | "Firefox" | None | +| 1 | `08d833ec-5eef-461c-b452-842e7bd27067` | 1 | "Chrome" | "www.google.com" | + +## Testing on a subset of events + +Depending on your Snowplow tracking configuration, you might want to test only on events from specific applications, using `app_ids`: + +```python +data = sp_signals.test( + view=my_view, + app_ids=["website"], +) +print(data) ``` -This makes the View live, and events will start being processed based on the defined attributes. +If you don't see any results, check your Signals configuration to confirm that it's processing events from those `app_id`s. From b90cc8d88591f3fc04d0cb7564e66c4662536ec9 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Thu, 17 Jul 2025 12:00:48 +0100 Subject: [PATCH 05/11] Tidy up batch engine tutorial --- tutorials/snowplow-batch-engine/conclusion.md | 14 ++- .../snowplow-batch-engine/generate-models.md | 92 +++++++------------ .../initialize-project.md | 82 ++++++----------- tutorials/snowplow-batch-engine/install.md | 29 ++++-- .../materialize-models.md | 48 +++++----- tutorials/snowplow-batch-engine/run-models.md | 61 +++++------- tutorials/snowplow-batch-engine/start.md | 60 ++++++------ .../snowplow-batch-engine/test-connection.md | 48 ++++------ 8 files changed, 191 insertions(+), 243 deletions(-) diff --git a/tutorials/snowplow-batch-engine/conclusion.md b/tutorials/snowplow-batch-engine/conclusion.md index 2bcc16a716..1e9006b181 100644 --- a/tutorials/snowplow-batch-engine/conclusion.md +++ b/tutorials/snowplow-batch-engine/conclusion.md @@ -3,4 +3,16 @@ position: 10 title: Conclusion --- -TODO +In this tutorial you've learned how to calculate attributes from your warehouse data, and apply them to Signals. + +This is the process workflow: +* Define batch view configurations and apply them to Signals +* Initialize dbt projects +* Generate models +* Configure the projects with dbt +* Create tables by running the models +* Connect the tables to Signals by materialization + +## Next steps + +Learn more about the Signals possibilities in our other Signals tutorials. diff --git a/tutorials/snowplow-batch-engine/generate-models.md b/tutorials/snowplow-batch-engine/generate-models.md index 57d2b086cf..39a191a37e 100644 --- a/tutorials/snowplow-batch-engine/generate-models.md +++ b/tutorials/snowplow-batch-engine/generate-models.md @@ -1,99 +1,75 @@ --- position: 4 -title: Generating Data Models for Batch Views +title: Generate data models --- -Now that your projects are set up, it's time to generate the data models for each batch view. Each project will have its own set of models generated based on its specific schema and requirements. +Each project will have its own set of models generated based on its specific schema and requirements. -## Generating Models - -Depending on how you initialized your projects, you can generate models in two ways: +For each project, the generation process will: -### For All Batch Views +1. Create dbt configuration files +2. Generate SQL models based on the batch view's schema +3. Set up necessary macros and functions +4. Update any existing files if needed -If you created projects for all batch views: +For each batch view, the generated models are specifically designed for batch processing: -```bash -snowplow-batch-autogen generate \ - --api-url "YOUR_API_URL" \ - --api-key "YOUR_API_KEY" \ - --api-key-id "YOUR_API_KEY_ID" \ - --org-id "YOUR_ORG_ID" \ - --repo-path "./my_snowplow_repo" \ - --verbose -``` +* Base models: raw data transformations +* Filtered events: event filtering and cleaning +* Daily aggregates: time-based aggregations +* Attributes: final feature definitions -This will generate models for each batch view project in your repository. +## Run generate command -### For a Specific Project +Depending on how you initialized your projects, you can generate models in two ways. -If you want to generate models for a specific project (remember that project names follow the format `{view_name}_{view_version}`): +If you created projects for all views, you can generate models for all of them at once: ```bash -snowplow-batch-autogen generate \ - --project-name "user_attributes_1" \ - --verbose +# For all views +snowplow-batch-autogen generate --verbose ``` -If you've set up your environment variables, you can use these simpler commands: +To generate models for a specific project: ```bash -# For all batch views -snowplow-batch-autogen generate --verbose - -# For a specific project -snowplow-batch-autogen generate --project-name "user_attributes_1" --verbose +snowplow-batch-autogen generate \ + --project-name "user_attributes_1" \ + --verbose ``` -## What Happens During Generation? - -For each project, the generation process will: - -1. Create dbt configuration files -2. Generate SQL models based on the batch view's schema -3. Set up necessary macros and functions -4. Update any existing files if needed +Remember that project names follow the format `{view_name}_{view_version}`. -## Project Structure After Generation +## Project structure After generation, each project in your repository will have this expanded structure: ``` my_snowplow_repo/ ├── user_attributes_1/ -│ ├── dbt_project.yml # Main dbt configuration -│ ├── packages.yml # Dependencies configuration -│ ├── models/ # SQL models -│ │ ├── base/ # Base models -│ │ ├── filtered_events/ # Event filtering -│ │ ├── daily_aggregates/ # Aggregated data -│ │ └── attributes/ # Feature definitions -│ ├── configs/ # Configuration files +│ ├── dbt_project.yml # Main dbt configuration +│ ├── packages.yml # Dependencies configuration +│ ├── models/ # SQL models +│ │ ├── base/ # Base models +│ │ ├── filtered_events/ # Event filtering +│ │ ├── daily_aggregates/ # Aggregated data +│ │ └── attributes/ # Feature definitions +│ ├── configs/ # Configuration files │ │ ├── base_config.json │ │ └── dbt_config.json -│ └── macros/ # Reusable SQL functions +│ │ └── batch_source_config.json +│ └── macros/ # Reusable SQL functions ├── product_views_2/ │ └── ... (same structure) └── user_segments_1/ └── ... (same structure) ``` -## Understanding the Generated Models - -For each batch view, the generated models are specifically designed for batch processing: - -- **Base models**: raw data transformations -- **Filtered events**: event filtering and cleaning -- **Daily aggregates**: time-based aggregations -- **Attributes**: final feature definitions - ## Troubleshooting If you encounter any issues during generation: -1. Make sure your projects were properly initialized in the correct path +1. Check that your projects were properly initialized in the correct path 2. Review the `base_config.json` file in each project for configuration issues 3. Check that your API credentials have the necessary permissions 4. Use the `--verbose` flag for more detailed error messages - -Once your models are generated, you're ready to run them and see the results! \ No newline at end of file diff --git a/tutorials/snowplow-batch-engine/initialize-project.md b/tutorials/snowplow-batch-engine/initialize-project.md index ffe7dcdcc2..ed5e664e16 100644 --- a/tutorials/snowplow-batch-engine/initialize-project.md +++ b/tutorials/snowplow-batch-engine/initialize-project.md @@ -1,66 +1,49 @@ --- position: 3 -title: Creating Projects for Batch Views +title: Create projects --- -Now that we've verified our connection to Snowplow Signals, let's create projects for your batch views. Each batch view will have its own separate dbt project in the specified repository path, with the project name following the format `{view_name}_{view_version}`. +Having tested the connection, you can now initialize your projects. -## Creating Projects - -You have two options when creating projects: +When you run the initialization command, the CLI will: -1. **Generate projects for all batch views**: Creates a separate project for each batch view in your repository -2. **Generate project for a specific view**: Creates a project for just one batch view +1. Create a separate project directory for each relevant view +2. Set up the basic configuration files for each project +3. Initialize the necessary folder structure for each project +4. Prepare each project for model generation -### Option 1: All Batch Views +## Run initialize -To create projects for all your batch views: +You can generate projects for all the relevant views in Signals at once, or one at a time. ```bash -snowplow-batch-autogen init \ - --api-url "YOUR_API_URL" \ - --api-key "YOUR_API_KEY" \ - --api-key-id "YOUR_API_KEY_ID" \ - --org-id "YOUR_ORG_ID" \ - --repo-path "./my_snowplow_repo" \ - --verbose -``` - -This will create a separate project directory for each batch view in your repository, with each directory named using the format `{view_name}_{view_version}`. - -### Option 2: Specific Batch View - -To create a project for a specific batch view: +# For all views +snowplow-batch-autogen init --verbose -```bash +# For a specific view snowplow-batch-autogen init \ --view-name "user_attributes" \ --view-version 1 \ --verbose ``` -If you've set up your environment variables, you can use these simpler commands: - -```bash -# For all batch views -snowplow-batch-autogen init --verbose - -# For a specific view -snowplow-batch-autogen init --view-name "user_attributes" --view-version 1 --verbose -``` +Each view will have its own separate dbt project, with the project name following the format `{view_name}_{view_version}`. -## What Happens During Initialization? +The files will be generated at the path specified in your `SNOWPLOW_REPO_PATH` environment variable. -When you run the initialization command, the CLI will: +## Project structure -1. Create a separate project directory for each batch view (named `{view_name}_{view_version}`) -2. Set up the basic configuration files for each project -3. Initialize the necessary folder structure for each project -4. Prepare each project for model generation +After initialization, your repository will have a structure like this: -## Project Structure +``` +my_repo/ +├── my_view_1/ +│ └── configs/ +│ └── base_config.json +├── etc. +``` -After initialization, your repository will have this structure: +In this example, projects were generated for three views: `user_attributes` v1, `product_views` v2, and `user_segments` v3: ``` my_snowplow_repo/ @@ -75,20 +58,11 @@ my_snowplow_repo/ └── base_config.json ``` -Each view gets its own project directory with its own configuration, named using the format `{view_name}_{view_version}`. - -## Choosing Between Options - -- Use **Option 1** when you want to set up projects for all your batch views at once -- Use **Option 2** when you want to work with a specific batch view - ## Troubleshooting If you run into any issues during initialization: -1. Make sure you have write permissions in the target directory -2. Verify that the view name and version combination doesn't already exist -3. Check that your API credentials have the necessary permissions -4. Use the `--verbose` flag to get more detailed error messages - -Once your projects are created, you're ready to generate the data models for each view! +1. Check that you have write permissions in the target directory +2. Check that you don't already have a project with the same name as one you're trying to initialize +4. Check that your API credentials have the necessary permissions +5. Use the `--verbose` flag to get more detailed error messages diff --git a/tutorials/snowplow-batch-engine/install.md b/tutorials/snowplow-batch-engine/install.md index 6297f5d96f..3f4feae6b6 100644 --- a/tutorials/snowplow-batch-engine/install.md +++ b/tutorials/snowplow-batch-engine/install.md @@ -3,26 +3,39 @@ position: 1.5 title: Install the CLI --- -To install the Signals Batch Engine CLI tool, run the following command: +Choose where to generate your Signals dbt models. We recommend creating a new repository. + +Navigate into your repo, and check you're in the intended Python environment. + +The batch engine is part of the Signals Python SDK. It's not installed by default, as not all use cases will need it. To install it, run the following command: ```bash pip install 'snowplow-signals[batch-engine]' ``` -This will install the CLI tool along with all necessary dependencies for working with batch views. +This will install the CLI tool as `snowplow-batch-autogen`, along with the necessary dependencies. + +## Available commands + +The available options are: -**Important**: Make sure you're in the correct Python environment (virtual environment, Poetry, etc.) where you want to install the CLI tool. The CLI commands will only work in the environment where the package is installed. +```bash + init # Initialize dbt project structure and base configuration + generate # Generate dbt project assets + materialize # Registers the attribute table as a data source with Signals + test_connection # Test the connection to the authentication and API services +``` -## Setting Up Environment Variables +A `--verbose` flag is available for every command. -To make your workflow smoother, you can set up your API credentials as environment variables. This way, you won't need to type them in every command: +## Set up environment variables + +To make your workflow smoother, set up your Signals credentials as environment variables. This way, you won't need to type them in every command: ```bash export SNOWPLOW_API_URL="YOUR_API_URL" export SNOWPLOW_API_KEY="YOUR_API_KEY" export SNOWPLOW_API_KEY_ID="YOUR_API_KEY_ID" export SNOWPLOW_ORG_ID="YOUR_ORG_ID" -export SNOWPLOW_REPO_PATH="./my_snowplow_repo" +export SNOWPLOW_REPO_PATH="./my_snowplow_repo" # Path to the repo where you want to generate projects ``` - -Ready to begin? Let's start by testing your connection to the Snowplow Signals services. diff --git a/tutorials/snowplow-batch-engine/materialize-models.md b/tutorials/snowplow-batch-engine/materialize-models.md index 6679cbfd3f..87f5ae7f94 100644 --- a/tutorials/snowplow-batch-engine/materialize-models.md +++ b/tutorials/snowplow-batch-engine/materialize-models.md @@ -1,49 +1,55 @@ --- position: 6 -title: Materializing Models to Signals +title: Materialize models --- -## What is Model Materialization? +Model materialization is the process of making your validated dbt models, and the calculated attributes, available in Signals for production use. -Model materialization is the process of taking your tested and validated dbt models and making them available in Snowplow Signals. This enables you to serve your attributes in production (with regular updates to keep the warehouse and Signals in sync) +There are two steps for materialization: +1. Fill out the `batch_source_config.json` file for each model +2. Run the `materialize` command -## Materializing your attribute table -Once you are happy with the dbt package generated outputs, you already have the attributes table in the warehouse, and you are ready to commit to it for production you are ready to start materializing your table. +You'll need to materialize each project individually. -### Step 1. - Fill out the batch_source_config -At the time of the data model generation, a config file is generated for you to adjust, under `config/batch_source_config.json`. You will see a similar structure to this: +The `materialize` command uses the [materialization engine](/docs/signals/configuration/batch-calculations#materialization-engine) under the hood. + +## Update configuration file + +During data model generation, a config file is generated in `config/batch_source_config.json`. It will have a similar structure to this: ```yml { - "database": "", - "wh_schema": "", - "table": "ecommerce_1_attributes", - "name": "ecommerce_1_attributes", + "database": "", # Add your database name + "wh_schema": "", # Add your schema + "table": "user_attributes_1_attributes", + "name": "user_attributes_1_attributes", "timestamp_field": "lower_limit", "created_timestamp_column": "valid_at_tstamp", - "description": "Table containing attributes for ecommerce_1 view", + "description": "Table containing attributes for user_attributes_1 view", "tags": {}, "owner": "" } ``` -Make sure you fill out the `database` and `wh_schema` (this will be your dbt profile's `{target_name}_derived`), which will need to correspond to the attributes table the dbt package has already produced. The rest you can leave unchanged. -### Step 2. - Run the materialize command +Fill out the `database` and `wh_schema` values. For schema, use your dbt profile's `{target_name}_derived`. These values will need to correspond to the attributes table the dbt package has already produced. + +## Run the materialize command Run the following CLI command: ```bash snowplow-batch-autogen materialize \ - --view-name "ecommerce" \ + --view-name "user_attributes" \ --view-version 1 \ --verbose ``` -Based on the output you will see if it was successful. First it attempts to register the Batch Source for the view in question, if all good you will see the relevant message: -✅ Successfully added Batch Source information to view ecommerce_1 +The batch engine will first register the batch source for the view. It will then update the Signals configuration to register the table. -It then updates Signals which registers the table and the syncing should automatically begin from that point onwards: - -✅ Successfully registered table ecommerce_transaction_interactions_features_1_attributes +```bash +# Progress messages +✅ Successfully added Batch Source information to view user_attributes_1 +✅ Successfully registered table user_attributes_1_attributes +``` -For now there is no way to alter the update schedule (default: every 5 minutes), but watch out for updates on this in the near future! +Syncing to the Profiles Store will begin automatically. By default, Signals will check for updates to the table every 5 minutes. Your attributes will soon be available to retrieve in your applications. diff --git a/tutorials/snowplow-batch-engine/run-models.md b/tutorials/snowplow-batch-engine/run-models.md index fe93d3f6a3..3f1a77652c 100644 --- a/tutorials/snowplow-batch-engine/run-models.md +++ b/tutorials/snowplow-batch-engine/run-models.md @@ -1,21 +1,28 @@ --- position: 5 -title: Running and Testing Your Models +title: Run and test models --- Now that your models are generated, it's time to run them and verify that everything works as expected. This step allows you to test your models locally before moving them to production. -## Prerequisites +Before running your new models, you'll need to configure their dbt connection profile. Read more about this in the [dbt documentation](https://docs.getdbt.com/docs/core/connect-data-platform/connection-profiles). The batch engine doesn't generate a `profiles.yml` because it isn't best practice to store credentials in the same place as models. -Before running your models, make sure you have: +During the run process: +* dbt will compile your SQL models +* Tables and views will be created in your data warehouse +* You'll see progress updates in the terminal +* Any errors will be clearly displayed -- A properly configured dbt profile for your data warehouse -- The necessary permissions to create tables and views -- Access to your data warehouse +Best practice to ensure successful model runs: +* Always test your models after generation +* Review the generated SQL for accuracy +* Document any custom modifications you make +* Keep track of model versions +* Regularly update your models as your data evolves -## Running Your Models +## Run the models -### First Run +After configuring dbt, you can run your models locally using the `dbt run` command. For your first run, you'll want to do a full refresh to ensure all tables are created properly: @@ -25,42 +32,20 @@ dbt run --full-refresh ![dbt first run](images/dbt_first_run.png) -### Subsequent Runs - For later runs, you can use the standard command: ```bash dbt run ``` -## What to Expect - -During the run process: - -1. dbt will compile your SQL models -2. Tables and views will be created in your data warehouse -3. You'll see progress updates in the terminal -4. Any errors will be clearly displayed - -## Best Practices - -To ensure successful model runs: - -1. Always test your models after generation -2. Review the generated SQL for accuracy -3. Document any custom modifications you make -4. Keep track of model versions -5. Regularly update your models as your data evolves - -## Testing and Validation - -This local testing phase is your opportunity to: +Running the models will create tables of your newly calculated attributes. -- Verify that the generated models meet your requirements -- Make any necessary adjustments to the models -- Explore the data transformations -- Ensure data quality and accuracy +## Test and validate -## Next Steps +It's important to test your models before moving them to production. The local testing phase is your opportunity to: +* Verify that the generated models meet your requirements +* Make any necessary adjustments to the models +* Explore the data transformations +* Ensure data quality and accuracy -After you're satisfied with your local testing results, you can proceed to materialize these models to your feature store for production use. \ No newline at end of file +Follow your standard dbt testing process. diff --git a/tutorials/snowplow-batch-engine/start.md b/tutorials/snowplow-batch-engine/start.md index ae890bf69c..20c8dd31fd 100644 --- a/tutorials/snowplow-batch-engine/start.md +++ b/tutorials/snowplow-batch-engine/start.md @@ -3,45 +3,37 @@ position: 1 title: Introduction --- -Welcome to the Signals Batch Engine guide! This tool helps you generate and manage dbt projects for batch processing of your Snowplow Signals attributes. +Welcome to the [Snowplow Signals](/docs/signals/) batch engine tutorial. -## What is Snowplow Signals? +Snowplow Signals is a real-time personalization engine for customer intelligence, built on Snowplow's behavioral data pipeline. It allows you to compute, access, and act on in-session stream and historical user data, in near real time. -Snowplow Signals is a feature store that helps you manage and serve machine learning features at scale. In the Profiles API, you can have different types of attribute views: +The Signals batch engine is a CLI tool to help with historical data analysis. It isn't required to use Signals: it's only necessary if you want to: +* Analyze historical data, rather than in real time +* Calculate attributes for Snowplow events in your warehouse -- **Batch Views**: processed offline, perfect for historical data and complex aggregations -- **Stream Views**: processed in real-time, ideal for immediate feature updates +The batch engine helps by: +* Generating separate dbt projects for each batch view definition +* Testing and validating your data pipelines +* Materializing calulated attributes to Signals for production use -This CLI tool specifically helps you work with batch views by: +To use tables of pre-existing, already calculated values, see the [Signals documentation](/docs/signals/configuration/batch-calculations). -- Generating separate dbt projects for each batch view -- Testing and validating your data pipelines -- Materializing features for production use +This guide will walk you through the steps to set up the batch engine and calculate attributes. ## Prerequisites -Before starting, ensure you have: - -- Python 3.11+ installed -- Snowplow Signals SDK installed -- Valid API credentials from your Snowplow Signals account: - - API URL - - API Key - - API Key ID - - Organization ID -- Have View(s) already created - -:::info -Make sure you specified `offline = True` in your View definition. -::: - -## What you'll learn - -This tutorial will guide you through the complete process of working with batch views in Snowplow Signals: - -1. Setting up your environment -2. Testing your connection to Snowplow Signals services -3. Creating projects for your batch views (either all views or a specific one) -4. Generating data models automatically -5. Running and testing your models -6. Materializing your models to the feature store +This tutorial assumes that you have: + +* Python 3.12+ installed in your environment +* Snowflake warehouse with tables of Snowplow events +* Permissions to create tables and views in your warehouse +* [dbt](https://www.getdbt.com/) configured in your warehouse +* Basic [dbt](https://www.getdbt.com/) knowledge +* Valid API credentials for your Signals account: + * Signals API URL + * Snowplow API key + * Snowplow API key ID + * Snowplow organization ID +* Batch view definitions already applied to Signals + +Check out the [Signals configuration](/docs/signals/configuration) documentation to find out how to generate these credentials, and how to apply attribute configurations. diff --git a/tutorials/snowplow-batch-engine/test-connection.md b/tutorials/snowplow-batch-engine/test-connection.md index 29f6f5187e..3e04cfa450 100644 --- a/tutorials/snowplow-batch-engine/test-connection.md +++ b/tutorials/snowplow-batch-engine/test-connection.md @@ -1,16 +1,25 @@ --- position: 2 -title: Testing Your Connection +title: Test the connection --- -Before we start working with Snowplow Signals, let's make sure we can connect to all the necessary services. This step is crucial as it verifies that: -- Your API credentials are correct -- All required services are accessible -- Your network connection is working properly +The first step is to confirm that you can connect to all the necessary services. -## Testing the Connection +The connection test checks several important components: +* Verifies your API credentials +* Ensures the main Signals API service is accessible +* Checks the status of: + * Database connections + * Cache service + * Storage systems -You can test your connection using the following command: +Test your connection using the following command: + +```bash +snowplow-batch-autogen test-connection --verbose +``` + +If you didn't set up environment variables, you can also provide the credentials as command-line flags: ```bash snowplow-batch-autogen test-connection \ @@ -21,25 +30,6 @@ snowplow-batch-autogen test-connection \ --verbose ``` -If you've set up the environment variables as shown in the previous step, you can use this simpler command: - -```bash -snowplow-batch-autogen test-connection --verbose -``` - -## What's Being Tested? - -The connection test checks several important components: - -- 🔐 Authentication service: verifies your API credentials -- 🌐 API service: ensures the main service is accessible -- 📊 Checks the status of: - - Database connections - - Cache service - - Storage systems - -## Successful Connection - When everything is working correctly, you'll see a clear success message: ```bash @@ -56,7 +46,9 @@ When everything is working correctly, you'll see a clear success message: ✨ All services are operational! ``` -## Troubleshooting Connection Issues +You can continue to the next step. + +## Troubleshooting If you encounter any problems: @@ -65,5 +57,3 @@ If you encounter any problems: 3. Ensure your API key has the required permissions 4. Use the `--verbose` flag for detailed error messages 5. Check if your organization's services are up and running - -Once you see the success message, you're ready to create your first project! From fe9b363f5ba9917b3ff413ba59b0b8ab270ecdf6 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Thu, 17 Jul 2025 13:31:54 +0100 Subject: [PATCH 06/11] Add notebook secrets image to quick start --- tutorials/signals-end-to-end/meta.json | 5 ---- .../signals-ml-prospect-scoring/conclusion.md | 22 ++++++++++++++++++ .../define-prospect-attributes.md | 0 .../intro.md | 11 +++++---- .../signals-ml-prospect-scoring/meta.json | 5 ++++ .../prerequisites-and-setup.md | 0 .../review-api-deployment.md | 0 .../screenshots/colab_credentials.jpeg | Bin .../screenshots/console_output.png | Bin .../screenshots/get_domain_userid.png | Bin .../screenshots/model_evaluate.png | Bin .../screenshots/prediction-structure.png | Bin .../screenshots/runtime_run_all.png | Bin .../screenshots/signals_test_output.png | Bin .../screenshots/solution_overview.png | Bin .../train-ml-prospect-scoring.md | 0 .../images/notebook-secrets.png | Bin 0 -> 167696 bytes tutorials/signals-quickstart/install.md | 4 +++- 18 files changed, 37 insertions(+), 10 deletions(-) delete mode 100644 tutorials/signals-end-to-end/meta.json create mode 100644 tutorials/signals-ml-prospect-scoring/conclusion.md rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/define-prospect-attributes.md (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/intro.md (68%) create mode 100644 tutorials/signals-ml-prospect-scoring/meta.json rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/prerequisites-and-setup.md (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/review-api-deployment.md (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/colab_credentials.jpeg (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/console_output.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/get_domain_userid.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/model_evaluate.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/prediction-structure.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/runtime_run_all.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/signals_test_output.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/screenshots/solution_overview.png (100%) rename tutorials/{signals-end-to-end => signals-ml-prospect-scoring}/train-ml-prospect-scoring.md (100%) create mode 100644 tutorials/signals-quickstart/images/notebook-secrets.png diff --git a/tutorials/signals-end-to-end/meta.json b/tutorials/signals-end-to-end/meta.json deleted file mode 100644 index d43738393d..0000000000 --- a/tutorials/signals-end-to-end/meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "Live Prospect Scoring with Snowplow Signals", - "label": "Solution accelerator", - "description": "This tutorial walks you through the process of setting up Snowplow Signals to do live prospect scoring." -} diff --git a/tutorials/signals-ml-prospect-scoring/conclusion.md b/tutorials/signals-ml-prospect-scoring/conclusion.md new file mode 100644 index 0000000000..2660ab80e2 --- /dev/null +++ b/tutorials/signals-ml-prospect-scoring/conclusion.md @@ -0,0 +1,22 @@ +--- +position: 10 +title: Conclusion +--- + +TODO + diff --git a/tutorials/signals-end-to-end/define-prospect-attributes.md b/tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md similarity index 100% rename from tutorials/signals-end-to-end/define-prospect-attributes.md rename to tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md diff --git a/tutorials/signals-end-to-end/intro.md b/tutorials/signals-ml-prospect-scoring/intro.md similarity index 68% rename from tutorials/signals-end-to-end/intro.md rename to tutorials/signals-ml-prospect-scoring/intro.md index 8960f3f0fb..0fa70cf260 100644 --- a/tutorials/signals-end-to-end/intro.md +++ b/tutorials/signals-ml-prospect-scoring/intro.md @@ -1,13 +1,16 @@ --- -title: Introduction and Overview +title: Introduction position: 1 --- -This tutorial will guide you through the process of building a real-time prospect scoring system using Snowplow Signals together with a machine learning model. +Welcome to the [Snowplow Signals](/docs/signals/) real-time prospect scoring tutorial. -By the end, you'll understand how to leverage Snowplow event data to predict a prospect's likelihood to convert on your website and trigger personalized engagements. +Snowplow Signals is a real-time personalization engine for customer intelligence, built on Snowplow's behavioral data pipeline. It allows you to compute, access, and act on in-session stream and historical user data, in near real time. + +This guide will through the process of building a real-time prospect scoring system using Signals together with a machine learning model. You'll learn how to leverage Snowplow event data to predict a prospect's likelihood to convert on your website, and how to trigger personalized engagements. + +Use this tutorial as a starting point for how to integrate Signals data with any ML use cases or other backend services. -Use this tutorial as a starting point for how one can integrate Signals data with any ML use cases or other backend services. ### Prospect Journey Overview diff --git a/tutorials/signals-ml-prospect-scoring/meta.json b/tutorials/signals-ml-prospect-scoring/meta.json new file mode 100644 index 0000000000..e29f41d60d --- /dev/null +++ b/tutorials/signals-ml-prospect-scoring/meta.json @@ -0,0 +1,5 @@ +{ + "title": "Score prospects in real time using Signals and ML", + "label": "Signals", + "description": "Try out Signals for live prospect scoring with machine learning." +} diff --git a/tutorials/signals-end-to-end/prerequisites-and-setup.md b/tutorials/signals-ml-prospect-scoring/prerequisites-and-setup.md similarity index 100% rename from tutorials/signals-end-to-end/prerequisites-and-setup.md rename to tutorials/signals-ml-prospect-scoring/prerequisites-and-setup.md diff --git a/tutorials/signals-end-to-end/review-api-deployment.md b/tutorials/signals-ml-prospect-scoring/review-api-deployment.md similarity index 100% rename from tutorials/signals-end-to-end/review-api-deployment.md rename to tutorials/signals-ml-prospect-scoring/review-api-deployment.md diff --git a/tutorials/signals-end-to-end/screenshots/colab_credentials.jpeg b/tutorials/signals-ml-prospect-scoring/screenshots/colab_credentials.jpeg similarity index 100% rename from tutorials/signals-end-to-end/screenshots/colab_credentials.jpeg rename to tutorials/signals-ml-prospect-scoring/screenshots/colab_credentials.jpeg diff --git a/tutorials/signals-end-to-end/screenshots/console_output.png b/tutorials/signals-ml-prospect-scoring/screenshots/console_output.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/console_output.png rename to tutorials/signals-ml-prospect-scoring/screenshots/console_output.png diff --git a/tutorials/signals-end-to-end/screenshots/get_domain_userid.png b/tutorials/signals-ml-prospect-scoring/screenshots/get_domain_userid.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/get_domain_userid.png rename to tutorials/signals-ml-prospect-scoring/screenshots/get_domain_userid.png diff --git a/tutorials/signals-end-to-end/screenshots/model_evaluate.png b/tutorials/signals-ml-prospect-scoring/screenshots/model_evaluate.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/model_evaluate.png rename to tutorials/signals-ml-prospect-scoring/screenshots/model_evaluate.png diff --git a/tutorials/signals-end-to-end/screenshots/prediction-structure.png b/tutorials/signals-ml-prospect-scoring/screenshots/prediction-structure.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/prediction-structure.png rename to tutorials/signals-ml-prospect-scoring/screenshots/prediction-structure.png diff --git a/tutorials/signals-end-to-end/screenshots/runtime_run_all.png b/tutorials/signals-ml-prospect-scoring/screenshots/runtime_run_all.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/runtime_run_all.png rename to tutorials/signals-ml-prospect-scoring/screenshots/runtime_run_all.png diff --git a/tutorials/signals-end-to-end/screenshots/signals_test_output.png b/tutorials/signals-ml-prospect-scoring/screenshots/signals_test_output.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/signals_test_output.png rename to tutorials/signals-ml-prospect-scoring/screenshots/signals_test_output.png diff --git a/tutorials/signals-end-to-end/screenshots/solution_overview.png b/tutorials/signals-ml-prospect-scoring/screenshots/solution_overview.png similarity index 100% rename from tutorials/signals-end-to-end/screenshots/solution_overview.png rename to tutorials/signals-ml-prospect-scoring/screenshots/solution_overview.png diff --git a/tutorials/signals-end-to-end/train-ml-prospect-scoring.md b/tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md similarity index 100% rename from tutorials/signals-end-to-end/train-ml-prospect-scoring.md rename to tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md diff --git a/tutorials/signals-quickstart/images/notebook-secrets.png b/tutorials/signals-quickstart/images/notebook-secrets.png new file mode 100644 index 0000000000000000000000000000000000000000..d9732e3ae48d7a298aa6c5895bc04945da6fc4b4 GIT binary patch literal 167696 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%0DGLc`0_!b6**?!@mfaHI0V*fc$ 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 P5%8z2ZlH#`Y9IbT@*>~$ literal 0 HcmV?d00001 diff --git a/tutorials/signals-quickstart/install.md b/tutorials/signals-quickstart/install.md index 38ddfa380b..6737cf00e2 100644 --- a/tutorials/signals-quickstart/install.md +++ b/tutorials/signals-quickstart/install.md @@ -27,7 +27,9 @@ Add your four connection tokens to the notebook secrets: * API key ID * Organization ID -Create a `Signals` object by passing in the required values. This example shows how to access notebook secrets, assuming you gave them these names: +![A screenshot showing where to add secrets into the notebook](./images/notebook-secrets.png) + +Create a `Signals` object by passing in the required values: ```python from snowplow_signals import Signals From 3370a5d081fe6c2e32d033db7d9e9b9b5799e63f Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Thu, 17 Jul 2025 13:54:34 +0100 Subject: [PATCH 07/11] Add inspector example to quick start --- .../signals-quickstart/define-attribute.md | 2 +- .../images/inspector-session.png | Bin 0 -> 65659 bytes .../signals-quickstart/retrieve-attributes.md | 12 +++++++----- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 tutorials/signals-quickstart/images/inspector-session.png diff --git a/tutorials/signals-quickstart/define-attribute.md b/tutorials/signals-quickstart/define-attribute.md index e3be15c197..241c0ca1d9 100644 --- a/tutorials/signals-quickstart/define-attribute.md +++ b/tutorials/signals-quickstart/define-attribute.md @@ -28,7 +28,7 @@ page_view_count = Attribute( version="1-0-0", ) ], - aggregation="counter" + aggregation="counter", period=timedelta(minutes=5), ) ``` diff --git a/tutorials/signals-quickstart/images/inspector-session.png b/tutorials/signals-quickstart/images/inspector-session.png new file mode 100644 index 0000000000000000000000000000000000000000..30d67feafe2591145438ad131cdec43f1c58511a GIT binary patch literal 65659 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 literal 0 HcmV?d00001 diff --git a/tutorials/signals-quickstart/retrieve-attributes.md b/tutorials/signals-quickstart/retrieve-attributes.md index beb5fd7a72..8e74eb084e 100644 --- a/tutorials/signals-quickstart/retrieve-attributes.md +++ b/tutorials/signals-quickstart/retrieve-attributes.md @@ -23,12 +23,14 @@ df=response.to_dataframe() df ``` -In your real application, you can access the current session ID and use it to retrieve the relevant attribute values. The attributes are being calculated in near real time, in session. +In your real application code, you can access the current session ID and use it to retrieve the relevant attribute values. The attributes are being calculated in near real time, in session. Read about how to access IDs such as `domain_sessionid` in your web application in [Getting cookie information](/docs/sources/trackers/web-trackers/cookies-and-local-storage/getting-cookie-values/#getdomainuserid). -In this tutorial example, it's harder to access anything interesting, as you might not know what sessions are active. +To test this out, use the [Snowplow Inspector](/docs/data-product-studio/data-quality/snowplow-inspector/) browser extension to find out your current session ID on your web application. Click around and generate some page view events. Then find your `Domain Session ID` in the Inspector. + +![Screenshot showing the session ID in the Snowplow Inspector](./images/inspector-session.png) + +Use this identifier to retrieve the attributes that Signals has just calculated about your session. | | `domain_sessionid` | `page_view_count` | `most_recent_browser` | `first_referrer_path` | | --- | -------------------------------------- | ----------------- | --------------------- | --------------------- | -| 0 | `d99f6db1-7b28-46ca-a3ef-f0aace99ed86` | None | None | None | - -Read about how to access IDs such as `domain_sessionid` in your web application in [Getting cookie information](/docs/sources/trackers/web-trackers/cookies-and-local-storage/getting-cookie-values/#getdomainuserid). +| 0 | `d99f6db1-7b28-46ca-a3ef-f0aace99ed86` | 2.0 | `Firefox` | `snowplow.io` | From f733058d292f2f7b345bf88f7945f085aade6a8d Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Thu, 17 Jul 2025 13:57:47 +0100 Subject: [PATCH 08/11] Specify correct python version --- tutorials/signals-quickstart/start.md | 2 +- tutorials/snowplow-batch-engine/start.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorials/signals-quickstart/start.md b/tutorials/signals-quickstart/start.md index 8d21c28ffa..69cf88ce15 100644 --- a/tutorials/signals-quickstart/start.md +++ b/tutorials/signals-quickstart/start.md @@ -13,7 +13,7 @@ This guide will walk you through the steps to calculate user behavior attributes This tutorial assumes that you have: -* Python 3.12+ installed in your environment +* Python 3.11+ installed in your environment * Basic Python and [Jupyter notebook](https://jupyter.org/) knowledge * Deployed Snowplow page view tracking from a web application * Snowflake warehouse diff --git a/tutorials/snowplow-batch-engine/start.md b/tutorials/snowplow-batch-engine/start.md index 20c8dd31fd..833fa502cf 100644 --- a/tutorials/snowplow-batch-engine/start.md +++ b/tutorials/snowplow-batch-engine/start.md @@ -24,7 +24,7 @@ This guide will walk you through the steps to set up the batch engine and calcul This tutorial assumes that you have: -* Python 3.12+ installed in your environment +* Python 3.11+ installed in your environment * Snowflake warehouse with tables of Snowplow events * Permissions to create tables and views in your warehouse * [dbt](https://www.getdbt.com/) configured in your warehouse From b3d8efd64105755f1b8f898349258e4a015abae9 Mon Sep 17 00:00:00 2001 From: Miranda Wilson Date: Mon, 21 Jul 2025 13:58:09 +0100 Subject: [PATCH 09/11] Tidy up attributes page --- .../signals-ml-prospect-scoring/conclusion.md | 13 + .../define-prospect-attributes.md | 342 ++++++++++++++---- .../signals-ml-prospect-scoring/intro.md | 62 ++-- .../prerequisites-and-setup.md | 47 --- .../review-api-deployment.md | 2 + .../signals-ml-prospect-scoring/setup.md | 43 +++ tutorials/signals-quickstart/install.md | 11 +- 7 files changed, 372 insertions(+), 148 deletions(-) delete mode 100644 tutorials/signals-ml-prospect-scoring/prerequisites-and-setup.md create mode 100644 tutorials/signals-ml-prospect-scoring/setup.md diff --git a/tutorials/signals-ml-prospect-scoring/conclusion.md b/tutorials/signals-ml-prospect-scoring/conclusion.md index 2660ab80e2..1198213a22 100644 --- a/tutorials/signals-ml-prospect-scoring/conclusion.md +++ b/tutorials/signals-ml-prospect-scoring/conclusion.md @@ -4,6 +4,19 @@ title: Conclusion --- TODO + + + +### End Result + +At the end of the tutorial, you will: + +* see live prospect attribute updates in the browser console, +* score them using an ML model, +* and use the outputs to drive decisions on the website. + +![](./screenshots/console_output.png) + +* Define more Signals attributes that are specific for your use cases and tracking +* Act on the prospect scores and predictions in your application +* Use attributes to trigger actions and decisions without modeling diff --git a/tutorials/signals-ml-prospect-scoring/create-endpoint.md b/tutorials/signals-ml-prospect-scoring/create-endpoint.md new file mode 100644 index 0000000000..00e82f5923 --- /dev/null +++ b/tutorials/signals-ml-prospect-scoring/create-endpoint.md @@ -0,0 +1,151 @@ +--- +title: Create API endpoint +position: 5 +--- + +You now have attribute values in your Profiles Store, and a trained ML model. The next step is to create and deploy an endpoint to serve attributes and predictions. + +It needs to do the following: +* Get calculated attribute values from Signals +* Score the values using the model +* Return the results + +This tutorial uses FastAPI for the endpoint, and ngrok to expose it outside of the Colab notebook. + +## Install dependencies + +Run `pip install fastapi nest-asyncio pyngrok uvicorn` to install the required libraries. + +## Define methods + +Start by loading your model, and defining the methods needed to retrieve and process your Signals data. + +```python +TODO imports + +# Load model +model = joblib.load("xgb_model.joblib") +explainer = joblib.load("shap_explainer.joblib") # shap.Explainer(model.named_steps['classifier']) + +# Retrieve attributes from Signals +sp_view = sp_signals.get_view("prospect_scoring") + +# Input schema +class InputData(BaseModel): + domain_userid: str + # ... add more input columns if needed + +# API +app = FastAPI() +app.add_middleware( + CORSMiddleware, + allow_origins=['*'], + allow_credentials=True, + allow_methods=['*'], + allow_headers=['*'], +) + +# Process the Signals data for individual domain_userids +def get_duid_values(duid: str): + response = sp_view.get_attributes( + signals=sp_signals, + identifier=duid + ) + df = pd.DataFrame([response]) + + # Add your own custom columns and filters + get_len = lambda x: len(x) if hasattr(x, '__len__') else 0 + df['day_of_week'] = datetime.date.today().isoweekday() + df[df.filter(like="num_").columns] = df.filter(like="num_").fillna(0) + + # Switch counter columns to booleans + df['had_conversions_l7d'] = (df['num_conversions_l7d'] > 0).astype(int) + df['had_conversions_l30d'] = (df['num_conversions_l30d'] > 0).astype(int) + df = df.drop(columns=['num_conversions_l7d', 'num_conversions_l30d']) + + # Switch unique arrays to amounts + df['num_sessions_l7d'] = df['num_sessions_l7d'].apply(get_len) + df['num_apps_l7d'] = df['num_apps_l7d'].apply(get_len) + df['num_sessions_l30d'] = df['num_sessions_l30d'].apply(get_len) + df['num_apps_l30d'] = df['num_apps_l30d'].apply(get_len) + df['num_engaged_campaigns_l30d'] = df['num_engaged_campaigns_l30d'].apply(get_len) + + # Reorder columns to follow the training order + df = df.reindex(columns=x_columns, fill_value=0) + return (df, pd.DataFrame([response])) + +# Prepare explanations +def get_prediction_explanations(df, top_n=5): + # Calculate shap values + df_transformed = model.named_steps['preprocessor'].transform(df) #.toarray() + feature_names = model.named_steps['preprocessor'].get_feature_names_out() + df_transformed_df = pd.DataFrame(df_transformed, columns=feature_names) + shap_values = explainer(df_transformed_df) + feature_contributions = dict(zip( + feature_names, + shap_values.values[0] + )) + # Group feature names: cat__feat_one_value1 -> feat_one + grouped = defaultdict(float) + for feat, val in feature_contributions.items(): + base = feat[5:].rsplit('_', 1)[0] if feat.startswith('cat__') else feat.split('__', 1)[1] + grouped[base] += val + sorted_grouped = dict(sorted(grouped.items(), key=lambda x: abs(x[1]), reverse=True)) + top_items = dict(list(sorted_grouped.items())[:top_n]) + sum_of_others = sum(sorted_grouped.values()) - sum(top_items.values()) + top_items["__sum_of_others"] = sum_of_others + top_items = {k: float(v) for k, v in top_items.items()} + return top_items + +# Score the data against the model +def get_predictions(df, explanations=None): + prediction = float(model.predict_proba(df)[:, 1][0]) + if explanations is None: + return prediction + top_contributors = get_prediction_explanations(df, explanations) + return (prediction, top_contributors) +``` + +## Create endpoint + +Create a `POST` HTTP endpoint using FastAPI. + +```python +@app.post("/predict") +def predict(data: InputData): + input_dict = data.model_dump() + + # Get Signals data and prepare dataframe for scoring + df, signals_response = get_duid_values(input_dict['domain_userid']) + + # Score the dataframe using the trained model + prediction, explanations = get_predictions(df, 5) + + # Return the result + print(f"P: {round(prediction, 4)} - {input_dict}") + return { + "signals": signals_response.to_dict(orient='records')[0], + "scoring_attributes": df.to_dict(orient='records')[0], + "explanations": explanations, + "score": prediction + } +``` + +This `/predict` endpoint does four things: + +1. Receives `domain_userid` +2. Calls the Signals API to get the latest attribute values using `sp_signals.get_online_attributes(...)` API TODO +3. Scores the attribute values using the ML model +4. Returns Signals attributes, a ML prediction score, and ML prediction explanations + +For example, in order to get live Signals Attributes for a `domain_userid` one can use this Signals API: TODO + +```python +def get_duid_values(duid: str): + response = sp_signals.get_online_attributes( + sp_view, + duid + ) + df = response.to_dataframe() + ... +``` diff --git a/tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md b/tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md index 77fdbd7f69..9c9898923a 100644 --- a/tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md +++ b/tutorials/signals-ml-prospect-scoring/define-prospect-attributes.md @@ -31,9 +31,13 @@ Since the attributes will be calculated in stream, those with a defined `period` With the exception of `num_media_events_l30d`, the attributes will be based on standard Snowplow web events such as `page_view`, `page_ping`, or `submit_form`. If you aren't tracking Snowplow media events, the `num_media_events_l30d` attribute value will just stay at 0. +## Install Signals Python SDK + +Run `pip install snowplow-signals`. + ## Define common variables -First, let's prepare the imports and useful variables. We will reuse the variables multiple times, and this makes the code concise and clear. +Let's prepare the imports and useful variables. We will reuse the variables multiple times, and this makes the code concise and clear. ```python diff --git a/tutorials/signals-ml-prospect-scoring/intro.md b/tutorials/signals-ml-prospect-scoring/intro.md index 2048684ab0..bd58a4f7ec 100644 --- a/tutorials/signals-ml-prospect-scoring/intro.md +++ b/tutorials/signals-ml-prospect-scoring/intro.md @@ -43,7 +43,7 @@ We're calculating aggregated attributes based off real-time stream event data, s * Snowplow API key * Snowplow API key ID * Snowplow organization ID -* [ngrok](https://dashboard.ngrok.com/) API key +* [ngrok](https://dashboard.ngrok.com/) account and Authtoken (API key) * Snowplow events in Snowflake: if you are using a different warehouse, adjust the connection code * Google Colab diff --git a/tutorials/signals-ml-prospect-scoring/review-api-deployment.md b/tutorials/signals-ml-prospect-scoring/review-api-deployment.md deleted file mode 100644 index e63451543b..0000000000 --- a/tutorials/signals-ml-prospect-scoring/review-api-deployment.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Test API Endpoint Code -position: 5 ---- - -### Create and Deploy Simple API Endpoint - -Navigate to the `Create Model Serving API Endpoint` section in the Colab where we create a simple HTTP endpoint with FastAPI. - -```python -... - -@app.post("/predict") -def predict(data: InputData): - input_dict = data.model_dump() - - # Get Signals data and prepare dataframe for scoring - df, signals_response = get_duid_values(input_dict['domain_userid']) - - # Score dataframe using the trained model - prediction, explanations = get_predictions(df, 5) - - # Return the result - print(f"P: {round(prediction, 4)} - {input_dict}") - return { - "signals": signals_response.to_dict(orient='records')[0], - "scoring_attributes": df.to_dict(orient='records')[0], - "explanations": explanations, - "score": prediction - } -``` - -Our `/predict` endpoint does these 4 things: - -1. Receives `domain_userid`. -2. Calls Signals API to get latest attribute values using `sp_signals.get_online_attributes(...)` API. -3. Scores latest attribute values using an ML model. -4. Returns Signals API attributes, ML prediction score, ML prediction explanations back. - -More implementation details are in each of the `get_duid_values, get_predictions` functions. - -For example, in order to get live Signals Attributes for a `domain_userid` one can use this Signals API: - -```python -def get_duid_values(duid: str): - response = sp_signals.get_online_attributes( - sp_view, - duid - ) - df = response.to_dataframe() - ... -``` - -### Proxy API Endpoint for Testing - -In order to be able to call this endpoint from your local machine or via JS in the browser, you need to proxy Colab's localhost to the world behind HTTPS. - -We will use ngrok to expose an endpoint from the Colab notebook behind an HTTPS URL. - -Let's use `ngrok` for that. -ngrok exposes Colab's localhost 8000 port behind a one-time HTTPS URL like `https://00ab-11-22-333-44.ngrok-free.app`. - -```python -import ... - -conf.get_default().auth_token = userdata.get('NGROK_TOKEN') -ngrok_tunnel = ngrok.connect(8000) -print('Public URL:', ngrok_tunnel.public_url) -nest_asyncio.apply() -uvicorn.run(app, port=8000) -``` - -As a result you should see this in the output. - -``` -Public URL: https://00ab-11-22-333-44.ngrok-free.app -... -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -### Perform Actions to Seed Signals with Data - -Go to your website and find your own `domain_userid`. - -You can use the [Snowplow Chrome Plugin](https://chromewebstore.google.com/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en&pli=1) to get it. - -![](./screenshots/get_domain_userid.png) - -### Test Using cURL - -Now take the ngrok API URL, your `domain_userid` and call the proxy using `cURL`: - -```bash -curl -X POST "https://00ab-11-22-333-44.ngrok-free.app/predict" -H "Content-Type: application/json" -d '{"domain_userid": "9a947ebb-5107-437c-b6c6-1d6cb6be3cf7"}' -``` - -### Test in the Browser Console - -Additionally, let's try this in the browser console to act on predictions: - -```js -// Let's call the API every 10s from the frontend -let base_url = "https://00ab-11-22-333-44.ngrok-free.app"; -let api_url = `${base_url}/predict`; -let tracker_name = "sp"; - -setInterval(function () { - // assuming Snowplow tracker is available at 'window.snowplow(...)' - window.snowplow(function () { - // get domain_userid - var sp = this[tracker_name]; - var domainUserId = sp.getDomainUserId(); - - // call the API - fetch(api_url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ domain_userid: domainUserId }) - }) - .then(response => response.json()) - .then(result => { - console.log("Prediction: ", domainUserId, " - ", result.score); - - // act on prediction - if (result.score >= 0.9) console.log('Prospect is likely to convert!'); - }) - .catch(console.error); - }); -}, 10 * 1000); -``` - -This simple snippet calls the API every 10 seconds. -Adjust it to call the endpoint APIs as often as needed in your use case. - -![](./screenshots/console_output.png) diff --git a/tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md b/tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md index 1051363fae..fde0dde0a4 100644 --- a/tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md +++ b/tutorials/signals-ml-prospect-scoring/train-ml-prospect-scoring.md @@ -13,6 +13,10 @@ Here's the prediction structure and timeline: The next task is to prepare historical data resembling the same Signals features, and train an XGBoost model on top. +## Install dependencies + +Run `pip install snowflake-connector-python snowflake-sqlalchemy` to install the required libraries. + ## Prepare training dataset Double-check that your `ENV_ATOMIC_TABLE` variable points to your Snowflake atomic table address, e.g. `snowplow_tracker_db.atomic.events`.