This package has been superseded by the Unified Digital that combines data from both web and mobile sources. For more information, see the Unified Digital page.
Snowplow Web Package
The package source code can be found in the snowplow/dbt-snowplow-web repo, and the docs for the model design here.
Take a look at some common analytical queries to run on the derived web data.
The package contains a fully incremental model that transforms raw web event data generated by the Snowplow JavaScript tracker into a series of derived tables of varying levels of aggregation.
The Snowplow web data model aggregates Snowplow's out of the box page view and page ping events to create a set of derived tables - page views, sessions and users - that contain many useful dimensions as well as calculated measures such as time engaged and scroll depth.
snowplow-web version | dbt versions | BigQuery | Databricks | Redshift | Snowflake | Postgres |
---|---|---|---|---|---|---|
1.0.1 | >=1.6.0 to <2.0.0 | โ | โ | โ | โ | โ |
0.16.2 | >=1.5.0 to <2.0.0 | โ | โ | โ | โ | โ |
0.15.2 | >=1.4.0 to <2.0.0 | โ | โ | โ | โ | โ * |
0.13.3** | >=1.3.0 to <2.0.0 | โ | โ | โ | โ | โ |
0.11.0 | >=1.0.0 to <1.3.0 | โ | โ | โ | โ | โ |
0.5.1 | >=0.20.0 to <1.0.0 | โ | โ | โ | โ | โ |
0.4.1 | >=0.18.0 to <0.20.0 | โ | โ | โ | โ | โ |
* Since version 0.15.0 of snowplow_web
at least version 15.0 of Postgres is required, otherwise you will need to overwrite the default_channel_group
macro to not use the regexp_like
function.
** From version v0.13.0 onwards we use the load_tstamp
field so you must be using RDB Loader v4.0.0 and above, or BigQuery Loader v1.0.0 and above. If you do not have this field because you are not using these versions, or you are using the Postgres loader, you will need to set snowplow__enable_load_tstamp
to false
in your dbt_project.yml
and will not be able to use the consent models.
Overviewโ
This model consists of a series of modules, each producing a table which serves as the input to the next module. The 'standard' modules are:
- Base: Performs the incremental logic, outputting the table
snowplow_web_base_events_this_run
which contains a de-duped data set of all events required for the current run of the model. - Page Views: Aggregates event level data to a page view level,
page_view_id
, outputting the tablesnowplow_web_page_views
. - Sessions: Aggregates event level data to a session level,
domain_sessionid
, outputting the tablesnowplow_web_sessions
. Includes other events but requires at least onepage_view
orpage_ping
event in the session. - Users: Aggregates session level data to a users level,
domain_userid
, outputting the tablesnowplow_web_users
. - User Mapping: Provides a mapping between user identifiers,
domain_userid
anduser_id
, outputting the tablesnowplow_web_user_mapping
. This can be used for session stitching.
Optional Modulesโ
๐๏ธ Conversions
Conversion events are a type of event that's important to your business, be that a transaction, a sign up to a newsletter, or the view of a specific page. Whatever type of event matters to you, so long as it can be determined from a single event record, you'll be able to model and aggregate these conversions at a session level with our package.
๐๏ธ Consent Module
๐๏ธ Core Web Vitals Module
Overridable Macrosโ
For information about overriding our macros, see here
filter_bots(table_alias)
source: used to define the filter to remove bot events from events processed by the package. Of the formand <condition>
. Used throughout the package to filter out bots from all models.channel_group_query()
source: defines the channel a user arrived at using various fields, populates thedefault_channel_group
field. Must be a valid sqlselect
object e.g. a completecase when
statement. Used insessions_this_run
table.engaged_session()
source: defines if a session was engaged or not, populates theis_engaged
field. Must returntrue
orfalse
and be a valid sqlselect
object e.g. a completecase when
statement. Used insessions_this_run
table.content_group_query()
source: defines the content groups by classifying the page urls for page views. Must be a valid sqlselect
object e.g. a completecase when
statement. Used inpage_views_this_run
table.
Engaged vs. Absolute Timeโ
At a page view- and session-level we provide two measures of time; absolute, how long a user had the page open, and engaged, how much of that time the user was on the page. Engaged time is often a large predictor of a customer conversion, such as a purchase or a sign-up, whatever that may be in your domain.
Calculating absolute time is simple, it's the difference between the derived_tstamp
of the first and last (page view or page ping) events within that page view/session.
The calculation for engaged time is more complicated, it is derived based on page pings which means if the user isn't active on your content, the engaged time does not increase. Let's consider a single page view example of reading an article; partway through the reader may see something they don't understand, so they open a new tab and look this up. They might stumble upon a Wikipedia page on it, they go down a rabbit hole and 10 minutes later they make it back to your site to finish the article. In this case there will be a gap for those 10 minutes in the page pings in the events data.
To adjust for these gaps we calculate engaged time as the time to trigger each ping (your heartbeat) times the number of pings (ignoring the first one), and add to that the time delay to the first ping (your minimum visit length). The formula is:
and the below shows an example visually for a single page view.
At a session level, this calculation is slightly more involved, as it needs to happen per page view and account for stray page pings, but the underlying idea is the same.
Stray Page Pingsโ
Stray Page Pings are pings within a session that do not have a corresponding page_view
event within the same session. The most common cause of these is someone returning to a tab after their session has timed out but not refreshing the page. The page_view
event exists in some other session, but there is no guarantee that both these sessions will be processed in the same run, which could lead to different results. Depending on your site content and user behavior the prevalence of sessions with stray page pings could vary greatly. For example with long-form content we have seen around 10% of all sessions contain only stray page pings (i.e. no page_view
events).
We take different approaches to adjust for these stray pings at the page view and sessions levels, which can lead to differences between the two tables, but each is as accurate as we can currently make it.
Sessionsโ
As all our processing ensures full sessions are reprocessed, our sessions level table includes all stray page ping events, as well as all other view and ping events. We adjust the start time down based on your minimum visit length if the session starts with a page ping, and we include sessions that contain only (stray) pings. We also count page views based on the number of unique page_view_ids
you have (from the web_page
context) rather than using absolute page_view
events to include these stray pings, and account for stray pings in the engaged time. Overall this is a more accurate view of a session and treats the stray pings as if they had a corresponding page_view
event in the same session, even when they did not.
The result of this is you may see misalignment between sessions and if you tried to recalculate them based directly off the page views table; this is because we discard stray pings during page view processing as discussed below, so the values (page_views
, engaged_time_in_s
, and absolute_time_in_s
) in the sessions table may be higher, but are more accurate at a session level.
Page Viewsโ
For page views, because we cannot guarantee the sessions with the page_view
event and all subsequent page_ping
events are processed within the same run, we choose to discard all stray page pings. Without doing this it could be possible that you would get different results from different run configurations.
Currently we do not process these discarded stray page pings in any way, meaning that engaged time and scroll depth in these cases may be under representative of the true value. Due to session level reprocessing this remains a complicated issue to resolve, but please let us know if you would like to help solve this!