From dce41d81f825f121db2c5c7b43718189e5c8949d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matu=CC=81s=CC=8C=20Tomlein?= Date: Tue, 4 Jul 2023 15:38:49 +0200 Subject: [PATCH] Replace snowplow_web with a base that is compatible with mobile events [WIP] --- dbt_project.yml | 101 +- .../snowplow_media_player_atomic_docs.md | 6 + .../snowplow_media_player_base_docs.md | 43 + .../snowplow_media_player_common_cols.md | 1148 +++++++++++++++++ .../snowplow_media_player_model_docs.md | 2 +- ...plow_media_player_media_stats_expected.csv | 2 +- ...plowanalytics_snowplow_media_player_1.csv} | 0 ...alytics_snowplow_media_player_event_1.csv} | 0 ..._snowplowanalytics_snowplow_web_page_1.csv | 249 ++++ ..._context.csv => com_youtube_youtube_1.csv} | 0 ...ext.csv => org_whatwg_media_element_1.csv} | 0 ...ext.csv => org_whatwg_video_element_1.csv} | 0 integration_tests/dbt_project.yml | 56 +- ...wplow__html5_media_element_context_stg.sql | 5 - ...wplow__html5_video_element_context_stg.sql | 7 - .../snowplow__media_player_context_stg.sql | 5 - ...owplow__media_player_event_context_stg.sql | 6 - .../default/snowplow__youtube_context_stg.sql | 6 - macros/allow_refresh.sql | 17 + macros/event_name_filter.sql | 14 + macros/snowplow_delete_from_manifest.sql | 3 + models/base/manifest/base_manifest.yml | 45 + ...media_player_base_quarantined_sessions.sql | 29 + ...layer_base_sessions_lifecycle_manifest.sql | 96 ++ ...plow_media_player_incremental_manifest.sql | 21 + .../scratch/base_scratch.yml} | 94 +- ...plow_media_player_base_events_this_run.sql | 305 +++++ ...plow_media_player_base_events_this_run.sql | 97 ++ ...plow_media_player_base_events_this_run.sql | 374 ++++++ .../scratch/default}/sources.yml | 0 ...low_media_player_base_events_this_run.sql} | 87 +- ...low_media_player_base_new_event_limits.sql | 24 + ...ow_media_player_base_sessions_this_run.sql | 31 + .../snowplow_media_player_pivot_base.sql | 13 +- models/base/src_base.yml | 267 ++++ .../custom/snowplow_media_player_custom.yml | 2 + models/web/scratch/base_scratch.yml | 67 + ...low_media_player_interactions_this_run.sql | 268 ---- ...low_media_player_interactions_this_run.sql | 83 -- ...low_media_player_interactions_this_run.sql | 207 --- .../snowplow_media_player_base_this_run.sql | 76 +- models/web/snowplow_media_player.yml | 2 + models/web/snowplow_media_player_base.sql | 3 +- .../web/snowplow_media_player_media_stats.sql | 64 +- packages.yml | 4 +- selectors.yml | 28 +- 46 files changed, 3135 insertions(+), 822 deletions(-) create mode 100644 docs/markdown/snowplow_media_player_base_docs.md rename integration_tests/data/source/{snowplow_media_player_context.csv => com_snowplowanalytics_snowplow_media_player_1.csv} (100%) rename integration_tests/data/source/{snowplow_media_player_event_context.csv => com_snowplowanalytics_snowplow_media_player_event_1.csv} (100%) create mode 100644 integration_tests/data/source/com_snowplowanalytics_snowplow_web_page_1.csv rename integration_tests/data/source/{snowplow_youtube_context.csv => com_youtube_youtube_1.csv} (100%) rename integration_tests/data/source/{snowplow_html5_media_element_context.csv => org_whatwg_media_element_1.csv} (100%) rename integration_tests/data/source/{snowplow_html5_video_element_context.csv => org_whatwg_video_element_1.csv} (100%) delete mode 100644 integration_tests/models/source/default/snowplow__html5_media_element_context_stg.sql delete mode 100644 integration_tests/models/source/default/snowplow__html5_video_element_context_stg.sql delete mode 100644 integration_tests/models/source/default/snowplow__media_player_context_stg.sql delete mode 100644 integration_tests/models/source/default/snowplow__media_player_event_context_stg.sql delete mode 100644 integration_tests/models/source/default/snowplow__youtube_context_stg.sql create mode 100644 macros/allow_refresh.sql create mode 100644 macros/event_name_filter.sql create mode 100644 macros/snowplow_delete_from_manifest.sql create mode 100644 models/base/manifest/base_manifest.yml create mode 100644 models/base/manifest/snowplow_media_player_base_quarantined_sessions.sql create mode 100644 models/base/manifest/snowplow_media_player_base_sessions_lifecycle_manifest.sql create mode 100644 models/base/manifest/snowplow_media_player_incremental_manifest.sql rename models/{web/scratch/snowplow_media_player_scratch.yml => base/scratch/base_scratch.yml} (58%) create mode 100644 models/base/scratch/bigquery/snowplow_media_player_base_events_this_run.sql create mode 100644 models/base/scratch/databricks/snowplow_media_player_base_events_this_run.sql create mode 100644 models/base/scratch/default/snowplow_media_player_base_events_this_run.sql rename models/{web/scratch/interactions_this_run/redshift_postgres => base/scratch/default}/sources.yml (100%) rename models/{web/scratch/interactions_this_run/snowflake/snowplow_media_player_interactions_this_run.sql => base/scratch/snowflake/snowplow_media_player_base_events_this_run.sql} (50%) create mode 100644 models/base/scratch/snowplow_media_player_base_new_event_limits.sql create mode 100644 models/base/scratch/snowplow_media_player_base_sessions_this_run.sql rename models/{web => base}/scratch/snowplow_media_player_pivot_base.sql (62%) create mode 100644 models/base/src_base.yml create mode 100644 models/web/scratch/base_scratch.yml delete mode 100644 models/web/scratch/interactions_this_run/bigquery/snowplow_media_player_interactions_this_run.sql delete mode 100644 models/web/scratch/interactions_this_run/databricks/snowplow_media_player_interactions_this_run.sql delete mode 100644 models/web/scratch/interactions_this_run/redshift_postgres/snowplow_media_player_interactions_this_run.sql diff --git a/dbt_project.yml b/dbt_project.yml index f3196a7..ba98367 100644 --- a/dbt_project.yml +++ b/dbt_project.yml @@ -24,46 +24,91 @@ clean-targets: - "dbt_packages" vars: - surrogate_key_treat_nulls_as_empty_strings: true # turn on legacy behavior + snowplow_media_player: + surrogate_key_treat_nulls_as_empty_strings: true # turn on legacy behavior + + # Sources + # snowplow__atomic_schema: 'atomic' # Only set if not using 'atomic' schema for Snowplow events data + # snowplow__database: # Only set if not using target.database for Snowplow events data -- WILL BE IGNORED FOR DATABRICKS + snowplow__events: "{{ source('atomic', 'events') }}" + snowplow__media_event_names: ['media_player_event'] + snowplow__number_checkout_steps: 4 + snowplow__number_category_levels: 4 + snowplow__categories_separator: '/' + snowplow__use_product_quantity: false + + snowplow__percent_progress_boundaries: [10, 25, 50, 75] + snowplow__valid_play_sec: 30 + snowplow__complete_play_rate: 0.99 + snowplow__max_media_pv_window: 10 + # please set any of the below three variables to true if the related context schemas are enabled for your warehouse, please note it cannot be used to filter the data: + # set to true if the YouTube context schema is enabled + snowplow__enable_youtube: false + # set to true if the HTML5 media element context schema is enabled + snowplow__enable_whatwg_media: false + # set to true if the HTML5 video element context schema is enabled + snowplow__enable_whatwg_video: false + snowplow__media_player_event_context: "com_snowplowanalytics_snowplow_media_player_event_1" + snowplow__media_player_context: "com_snowplowanalytics_snowplow_media_player_1" + snowplow__youtube_context: "com_youtube_youtube_1" + snowplow__html5_media_element_context: "org_whatwg_media_element_1" + snowplow__html5_video_element_context: "org_whatwg_video_element_1" + snowplow__context_web_page: 'com_snowplowanalytics_snowplow_web_page_1' + + # Variables - Standard Config + snowplow__start_date: '2020-01-01' + snowplow__backfill_limit_days: 30 + snowplow__app_id: [] + snowplow__derived_tstamp_partitioned: true + # Variables - Advanced Config + snowplow__lookback_window_hours: 6 + snowplow__session_lookback_days: 730 + snowplow__days_late_allowed: 3 + snowplow__max_session_days: 3 + snowplow__upsert_lookback_days: 30 + snowplow__query_tag: "snowplow_dbt" + snowplow__dev_target_name: 'dev' + snowplow__allow_refresh: false + snowplow__enable_load_tstamp: true + # Variables - Databricks Only + # Add the following variable to your dbt project's dbt_project.yml file + # Depending on the use case it should either be the catalog (for Unity Catalog users from databricks connector 1.1.1 onwards) or the same value as your snowplow__atomic_schema (unless changed it should be 'atomic') + # snowplow__databricks_catalog: 'hive_metastore' - snowplow__percent_progress_boundaries: [10, 25, 50, 75] - snowplow__valid_play_sec: 30 - snowplow__complete_play_rate: 0.99 - snowplow__max_media_pv_window: 10 - # please set any of the below three variables to true if the related context schemas are enabled for your warehouse, please note it cannot be used to filter the data: - # set to true if the YouTube context schema is enabled - snowplow__enable_youtube: false - # set to true if the HTML5 media element context schema is enabled - snowplow__enable_whatwg_media: false - # set to true if the HTML5 video element context schema is enabled - snowplow__enable_whatwg_video: false - snowplow__media_player_event_context: "{{ source('atomic', 'com_snowplowanalytics_snowplow_media_player_event_1') }}" - snowplow__media_player_context: "{{ source('atomic', 'com_snowplowanalytics_snowplow_media_player_1') }}" - snowplow__youtube_context: "{{ source('atomic', 'com_youtube_youtube_1') }}" - snowplow__html5_media_element_context: "{{ source('atomic', 'org_whatwg_media_element_1') }}" - snowplow__html5_video_element_context: "{{ source('atomic', 'org_whatwg_video_element_1') }}" +# # Completely or partially remove models from the manifest during run start. +# on-run-start: +# - "{{ snowplow_media_player_delete_from_manifest(var('models_to_remove',[])) }}" + +# # Update manifest table with last event consumed per sucessfully executed node/model +# on-run-end: +# - "{{ snowplow_utils.snowplow_incremental_post_hook('snowplow_media_player') }}" models: snowplow_media_player: +bind: false +materialized: view + base: + manifest: + +schema: "snowplow_manifest" + scratch: + +schema: "scratch" + +tags: "scratch" + bigquery: + +enabled: "{{ target.type == 'bigquery' | as_bool() }}" + databricks: + +enabled: "{{ target.type in ['databricks', 'spark'] | as_bool() }}" + default: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + snowflake: + +enabled: "{{ target.type == 'snowflake' | as_bool() }}" web: +schema: "derived" - +tags: "snowplow_web_incremental" + +tags: "snowplow_media_player_incremental" +enabled: true scratch: +schema: "scratch" +tags: "scratch" - interactions_this_run: - bigquery: - enabled: "{{ target.type == 'bigquery' | as_bool() }}" - databricks: - enabled: "{{ target.type in ['databricks', 'spark'] | as_bool() }}" - redshift_postgres: - enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" - snowflake: - enabled: "{{ target.type == 'snowflake' | as_bool() }}" custom: +schema: "scratch" - +tags: "snowplow_web_incremental" + +tags: "snowplow_media_player_incremental" +enabled: false diff --git a/docs/markdown/snowplow_media_player_atomic_docs.md b/docs/markdown/snowplow_media_player_atomic_docs.md index b329e42..3b3b8d4 100644 --- a/docs/markdown/snowplow_media_player_atomic_docs.md +++ b/docs/markdown/snowplow_media_player_atomic_docs.md @@ -21,3 +21,9 @@ This context table contains the entities related to the HTML5 Media Element, ada {% docs table_html_video_element_context %} This context table contains the entities related to the HTML5 Video Element, adapted from the whatwg spec. {% enddocs %} + +{% docs table_events %} + +The `events` table contains all canonical events generated by [Snowplow's](https://snowplow.io/) trackers, including web, mobile and server side events. + +{% enddocs %} diff --git a/docs/markdown/snowplow_media_player_base_docs.md b/docs/markdown/snowplow_media_player_base_docs.md new file mode 100644 index 0000000..4fbcafc --- /dev/null +++ b/docs/markdown/snowplow_media_player_base_docs.md @@ -0,0 +1,43 @@ +{% docs table_base_sessions_lifecycle_manifest %} + +This incremental table is a manifest of all sessions that have been processed by the Snowplow dbt ecommerce package. For each session, the start and end timestamp is recorded. + +By knowing the lifecycle of a session the model is able to able to determine which sessions and thus events to process for a given timeframe, as well as the complete date range required to reprocess all events of each session. + +{% enddocs %} + +{% docs table_base_incremental_manifest %} + +This incremental table is a manifest of the timestamp of the latest event consumed per model within the Snowplow dbt ecommerce package as well as any models leveraging the incremental framework provided by the package. The latest event's timestamp is based off `collector_tstamp`. This table is used to determine what events should be processed in the next run of the model. +{% enddocs %} + +{% docs table_base_new_event_limits %} + +This table contains the lower and upper timestamp limits for the given run of the web model. These limits are used to select new events from the events table. + +{% enddocs %} + + +{% docs table_base_events_this_run %} + +For any given run, this table contains all required events to be consumed by subsequent nodes in the Snowplow dbt ecommerce package. This is a cleaned, deduped dataset, containing all columns from the raw events table as well as having the `page_view_id` joined in from the page view context, and all of the fields parsed from the various e-commerce contexts except the `product` context. + +**Note: This table should be used as the input to any custom modules that require event level data, rather than selecting straight from `atomic.events`** + +{% enddocs %} + + +{% docs table_base_sessions_this_run %} + +For any given run, this table contains all the required sessions. + +{% enddocs %} + + +{% docs table_base_quarantined_sessions %} + +This table contains any sessions that have been quarantined. Sessions are quarantined once they exceed the maximum allowed session length, defined by `snowplow__max_session_days`. +Once quarantined, no further events from these sessions will be processed. Events up until the point of quarantine remain in your derived tables. +The reason for removing long sessions is to reduce table scans on both the events table and all derived tables. This improves performance greatly. + +{% enddocs %} diff --git a/docs/markdown/snowplow_media_player_common_cols.md b/docs/markdown/snowplow_media_player_common_cols.md index 7d7762e..0e52e7d 100644 --- a/docs/markdown/snowplow_media_player_common_cols.md +++ b/docs/markdown/snowplow_media_player_common_cols.md @@ -253,3 +253,1151 @@ If the video should restart after ending. {% docs col_volume %} Volume percent. {% enddocs %} + +{% docs col_app_id %} +Application ID e.g. ‘angry-birds’ is used to distinguish different applications that are being tracked by the same Snowplow stack, e.g. production versus dev. +{% enddocs %} + +{% docs col_platform %} +Platform e.g. ‘web’ +{% enddocs %} + +{% docs col_etl_tstamp %} +Timestamp event began ETL e.g. ‘2017-01-26 00:01:25.292’ +{% enddocs %} + + +{% docs col_dvce_created_tstamp %} +Timestamp event was recorded on the client device e.g. ‘2013-11-26 00:03:57.885’ +{% enddocs %} + +{% docs col_event %} +The type of event recorded e.g. ‘page_view’ +{% enddocs %} + + +{% docs col_txn_id %} +Transaction ID set client-side, used to de-dupe records e.g. 421828 +{% enddocs %} + + +{% docs col_name_tracker %} +Tracker namespace e.g. ‘sp1’ +{% enddocs %} + + +{% docs col_v_tracker %} +Tracker version e.g. ‘js-3.0.0’ +{% enddocs %} + + +{% docs col_v_collector %} +Collector version e.g. ‘ssc-2.1.0-kinesis’ +{% enddocs %} + + +{% docs col_v_etl %} +ETL version e.g. ‘snowplow-micro-1.1.0-common-1.4.2’ +{% enddocs %} + + +{% docs col_user_id %} +Unique ID set by business e.g. ‘jon.doe@email.com’ +{% enddocs %} + + +{% docs col_user_ipaddress %} +User IP address e.g. ‘92.231.54.234’ +{% enddocs %} + + +{% docs col_user_fingerprint %} +A user fingerprint generated by looking at the individual browser features e.g. 2161814971 +{% enddocs %} + + +{% docs col_domain_sessionidx %} +A visit / session index e.g. 3 +{% enddocs %} + + +{% docs col_network_userid %} +User ID set by Snowplow using 3rd party cookie e.g. ‘ecdff4d0-9175-40ac-a8bb-325c49733607’ +{% enddocs %} + + +{% docs col_geo_country %} +ISO 3166-1 code for the country the visitor is located in e.g. ‘GB’, ‘US’ +{% enddocs %} + + +{% docs col_geo_region %} +ISO-3166-2 code for country region the visitor is in e.g. ‘I9’, ‘TX’ +{% enddocs %} + + +{% docs col_geo_city %} +City the visitor is in e.g. ‘New York’, ‘London’ +{% enddocs %} + + +{% docs col_geo_zipcode %} +Postcode the visitor is in e.g. ‘94109’ +{% enddocs %} + + +{% docs col_geo_latitude %} +Visitor location latitude e.g. 37.443604 +{% enddocs %} + + +{% docs col_geo_longitude %} +Visitor location longitude e.g. -122.4124 +{% enddocs %} + + +{% docs col_ip_isp %} +Visitor’s ISP e.g. ‘FDN Communications’ +{% enddocs %} + + +{% docs col_ip_organization %} +Organization associated with the visitor’s IP address – defaults to ISP name if none is found e.g. ‘Bouygues Telecom’ +{% enddocs %} + + +{% docs col_ip_domain %} +Second level domain name associated with the visitor’s IP address e.g. ‘nuvox.net’ +{% enddocs %} + + +{% docs col_ip_netspeed %} +Visitor’s connection type e.g. ‘Cable/DSL’ +{% enddocs %} + + +{% docs col_page_title %} +Web page title e.g. ‘Snowplow Docs – Understanding the structure of Snowplow data’ +{% enddocs %} + + +{% docs col_page_urlscheme %} +Scheme aka protocol e.g. ‘https’ +{% enddocs %} + + +{% docs col_page_urlhost %} +Host aka domain e.g. ‘“www.snowplow.io’ +{% enddocs %} + + +{% docs col_page_urlport %} +Port if specified, 80 if not 80 +{% enddocs %} + + +{% docs col_page_urlpath %} +Path to page e.g. ‘/product/index.html’ +{% enddocs %} + + +{% docs col_page_urlquery %} +Querystring e.g. ‘id=GTM-DLRG’ +{% enddocs %} + + +{% docs col_page_urlfragment %} +Fragment aka anchor e.g. ‘4-conclusion’ +{% enddocs %} + + +{% docs col_refr_urlscheme %} +Referer scheme e.g. ‘http’ +{% enddocs %} + + +{% docs col_refr_urlhost %} +Referer host e.g. ‘www.bing.com’ +{% enddocs %} + + +{% docs col_refr_urlport %} +Referer port e.g. 80 +{% enddocs %} + + +{% docs col_refr_urlpath %} +Referer page path e.g. ‘/images/search’ +{% enddocs %} + + +{% docs col_refr_urlquery %} +Referer URL querystring e.g. ‘q=psychic+oracle+cards’ +{% enddocs %} + + +{% docs col_refr_urlfragment %} +Referer URL fragment +{% enddocs %} + + +{% docs col_refr_medium %} +Type of referer e.g. ‘search’, ‘internal’ +{% enddocs %} + + +{% docs col_refr_source %} +Name of referer if recognised e.g. ‘Bing images’ +{% enddocs %} + + +{% docs col_refr_term %} +Keywords if source is a search engine e.g. ‘psychic oracle cards’ +{% enddocs %} + + +{% docs col_mkt_medium %} +Type of traffic source e.g. ‘cpc’, ‘affiliate’, ‘organic’, ‘social’ +{% enddocs %} + + +{% docs col_mkt_source %} +The company / website where the traffic came from e.g. ‘Google’, ‘Facebook’ +{% enddocs %} + + +{% docs col_mkt_term %} +Any keywords associated with the referrer e.g. ‘new age tarot decks’ +{% enddocs %} + + +{% docs col_mkt_content %} +The content of the ad. (Or an ID so that it can be looked up.) e.g. 13894723 +{% enddocs %} + + +{% docs col_mkt_campaign %} +The campaign ID e.g. ‘diageo-123’ +{% enddocs %} + + +{% docs col_se_category %} +Category of event e.g. ‘ecomm’, ‘video’ +{% enddocs %} + + +{% docs col_se_action %} +Action performed / event name e.g. ‘add-to-basket’, ‘play-video’ +{% enddocs %} + + +{% docs col_se_label %} +The object of the action e.g. the ID of the video played or SKU of the product added-to-basket e.g. ‘pbz00123’ +{% enddocs %} + + +{% docs col_se_property %} +A property associated with the object of the action e.g. ‘HD’, ‘large’ +{% enddocs %} + + +{% docs col_se_value %} +A value associated with the event / action e.g. the value of goods added-to-basket e.g. 9.99 +{% enddocs %} + + +{% docs col_tr_orderid %} +Order ID e.g. ‘#134’ +{% enddocs %} + + +{% docs col_tr_affiliation %} +Transaction affiliation (e.g. store where sale took place) e.g. ‘web’ +{% enddocs %} + + +{% docs col_tr_total %} +Total transaction value e.g. 12.99 +{% enddocs %} + + +{% docs col_tr_tax %} +Total tax included in transaction value e.g. 3.00 +{% enddocs %} + + +{% docs col_tr_shipping %} +Delivery cost charged e.g. 0.00 +{% enddocs %} + + +{% docs col_tr_city %} +Delivery address, city e.g. ‘London’ +{% enddocs %} + + +{% docs col_tr_state %} +Delivery address, state e.g. ‘Washington’ +{% enddocs %} + + +{% docs col_tr_country %} +Delivery address, country e.g. ‘France’ +{% enddocs %} + + +{% docs col_ti_orderid %} +Order ID e.g. ‘#134’ +{% enddocs %} + + +{% docs col_ti_sku %} +Product SKU e.g. ‘pbz00123’ +{% enddocs %} + + +{% docs col_ti_name %} +Product name e.g. ‘Cone pendulum’ +{% enddocs %} + + +{% docs col_ti_category %} +Product category e.g. ‘New Age’ +{% enddocs %} + + +{% docs col_ti_price %} +Product unit price e.g. 9.99 +{% enddocs %} + + +{% docs col_ti_quantity %} +Number of product in transaction e.g. 2 +{% enddocs %} + + +{% docs col_pp_xoffset_min %} +Minimum page x offset seen in the last ping period e.g. 0 +{% enddocs %} + + +{% docs col_pp_xoffset_max %} +Maximum page x offset seen in the last ping period e.g. 100 +{% enddocs %} + + +{% docs col_pp_yoffset_min %} +Minimum page y offset seen in the last ping period e.g. 0 +{% enddocs %} + + +{% docs col_pp_yoffset_max %} +Maximum page y offset seen in the last ping period e.g. 200 +{% enddocs %} + + +{% docs col_useragent %} +Raw useragent +{% enddocs %} + + +{% docs col_br_family %} +Browser family e.g. ‘Firefox’ +{% enddocs %} + + +{% docs col_br_version %} +Browser version e.g. ‘12.0’ +{% enddocs %} + + +{% docs col_br_type %} +Browser type e.g. ‘Browser’ +{% enddocs %} + + +{% docs col_br_renderengine %} +Browser rendering engine e.g. ‘GECKO’ +{% enddocs %} + + +{% docs col_br_lang %} +Language the browser is set to e.g. ‘en-GB’ +{% enddocs %} + + +{% docs col_br_features_pdf %} +Whether the browser recognizes PDFs e.g. True +{% enddocs %} + + +{% docs col_br_features_flash %} +Whether Flash is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_java %} +Whether Java is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_director %} +Whether Adobe Shockwave is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_quicktime %} +Whether QuickTime is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_realplayer %} +Whether RealPlayer is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_windowsmedia %} +Whether mplayer2 is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_gears %} +Whether Google Gears is installed e.g. True +{% enddocs %} + + +{% docs col_br_features_silverlight %} +Whether Microsoft Silverlight is installed e.g. True +{% enddocs %} + + +{% docs col_br_cookies %} +Whether cookies are enabled e.g. True +{% enddocs %} + + +{% docs col_br_colordepth %} +Bit depth of the browser color palette e.g. 24 +{% enddocs %} + + +{% docs col_br_viewwidth %} +Viewport width e.g. 1000 +{% enddocs %} + + +{% docs col_br_viewheight %} +Viewport height e.g. 1000 +{% enddocs %} + + +{% docs col_os_family %} +Operating system family e.g. ‘Linux’ +{% enddocs %} + + +{% docs col_os_manufacturer %} +Company responsible for OS e.g. ‘Apple’ +{% enddocs %} + + +{% docs col_dvce_ismobile %} +Is the device mobile? e.g. True +{% enddocs %} + + +{% docs col_dvce_screenwidth %} +Screen width in pixels e.g. 1900 +{% enddocs %} + + +{% docs col_dvce_screenheight %} +Screen height in pixels e.g. 1024 +{% enddocs %} + + +{% docs col_doc_charset %} +The page’s character encoding e.g. , ‘UTF-8’ +{% enddocs %} + + +{% docs col_doc_width %} +The page’s width in pixels e.g. 1024 +{% enddocs %} + + +{% docs col_doc_height %} +The page’s height in pixels e.g. 3000 +{% enddocs %} + + +{% docs col_tr_currency %} +Currency e.g. ‘USD’ +{% enddocs %} + + +{% docs col_tr_total_base %} +Total in base currency e.g. 12.99 +{% enddocs %} + + +{% docs col_tr_tax_base %} +Total tax in base currency e.g. 3.00 +{% enddocs %} + + +{% docs col_tr_shipping_base %} +decimal Delivery cost in base currency e.g. 0.00 +{% enddocs %} + + +{% docs col_ti_currency %} +Currency e.g. ‘EUR’ +{% enddocs %} + + +{% docs col_ti_price_base %} +decimal Price in base currency e.g. 9.99 +{% enddocs %} + + +{% docs col_base_currency %} +Reporting currency e.g. ‘GBP’ +{% enddocs %} + + +{% docs col_geo_timezone %} +Visitor timezone name e.g. ‘Europe/London’ +{% enddocs %} + + +{% docs col_mkt_clickid %} +The click ID e.g. ‘ac3d8e459’ +{% enddocs %} + + +{% docs col_mkt_network %} +The ad network to which the click ID belongs e.g. ‘DoubleClick’ +{% enddocs %} + + +{% docs col_etl_tags %} +JSON of tags for this ETL run e.g. “[‘prod’]” +{% enddocs %} + + +{% docs col_dvce_sent_tstamp %} +When the event was sent by the client device e.g. ‘2013-11-26 00:03:58.032’ +{% enddocs %} + + +{% docs col_refr_domain_userid %} +The Snowplow domain_userid of the referring website e.g. ‘bc2e92ec6c204a14’ +{% enddocs %} + + +{% docs col_refr_dvce_tstamp %} +The time of attaching the domain_userid to the inbound link e.g. ‘2013-11-26 00:02:05’ +{% enddocs %} + + +{% docs col_event_vendor %} +Who defined the event e.g. ‘com.acme’ +{% enddocs %} + + +{% docs col_event_name %} +Event name e.g. ‘link_click’ +{% enddocs %} + + +{% docs col_event_format %} +Format for event e.g. ‘jsonschema’ +{% enddocs %} + + +{% docs col_event_version %} +Version of event schema e.g. ‘1-0-2’ +{% enddocs %} + + +{% docs col_event_fingerprint %} +Hash client-set event fields e.g. AADCE520E20C2899F4CED228A79A3083 +{% enddocs %} + + +{% docs col_true_tstamp %} +User-set “true timestamp” for the event e.g. ‘2013-11-26 00:02:04’ +{% enddocs %} + +{% docs col_category %} +Category based on activity if the IP/UA is a spider or robot, BROWSER otherwise +{% enddocs %} + + +{% docs col_primary_impact %} +Whether the spider or robot would affect page impression measurement, ad impression measurement, both or none +{% enddocs %} + + +{% docs col_reason %} +Type of failed check if the IP/UA is a spider or robot, PASSED_ALL otherwise +{% enddocs %} + + +{% docs col_spider_or_robot %} +True if the IP address or user agent checked against the list is a spider or robot, false otherwise +{% enddocs %} + + +{% docs col_device_family %} +Device type +{% enddocs %} + + +{% docs col_ua_os_family %} +Operation system name +{% enddocs %} + + +{% docs col_useragent_family %} +Useragent family (browser) name +{% enddocs %} + + +{% docs col_os_major %} +Operation system major version +{% enddocs %} + + +{% docs col_os_minor %} +Operation system minor version +{% enddocs %} + + +{% docs col_os_patch %} +Operation system patch version +{% enddocs %} + + +{% docs col_os_patch_minor %} +Operation system patch minor version +{% enddocs %} + + +{% docs col_os_version %} +Operation system full version +{% enddocs %} + + +{% docs col_useragent_major %} +Useragent major version +{% enddocs %} + + +{% docs col_useragent_minor %} +Useragent minor version +{% enddocs %} + + +{% docs col_useragent_patch %} +Useragent patch version +{% enddocs %} + + +{% docs col_useragent_version %} +Full version of the useragent +{% enddocs %} + + +{% docs col_device_class %} +Class of device e.g. phone +{% enddocs %} + + +{% docs col_agent_class %} +Class of agent e.g. browser +{% enddocs %} + + +{% docs col_agent_name %} +Name of agent e.g. Chrome +{% enddocs %} + + +{% docs col_agent_name_version %} +Name and version of agent e.g. Chrome 53.0.2785.124 +{% enddocs %} + + +{% docs col_agent_name_version_major %} +Name and major version of agent e.g. Chrome 53 +{% enddocs %} + + +{% docs col_agent_version %} +Version of agent e.g. 53.0.2785.124 +{% enddocs %} + + +{% docs col_agent_version_major %} +Major version of agent e.g. 53 +{% enddocs %} + + +{% docs col_device_brand %} +Brand of device e.g. Google +{% enddocs %} + + +{% docs col_device_name %} +Name of device e.g. Google Nexus 6 +{% enddocs %} + + +{% docs col_device_version %} +Version of device e.g. 6.0 +{% enddocs %} + + +{% docs col_layout_engine_class %} +Class of layout engine e.g. Browser +{% enddocs %} + + +{% docs col_layout_engine_name %} +Name of layout engine e.g. Blink +{% enddocs %} + + +{% docs col_layout_engine_name_version %} +Name and version of layout engine e.g. Blink 53.0 +{% enddocs %} + + +{% docs col_layout_engine_name_version_major %} +Name and major version of layout engine e.g. Blink 53 +{% enddocs %} + + +{% docs col_layout_engine_version %} +Version of layout engine e.g. 53.0 +{% enddocs %} + + +{% docs col_layout_engine_version_major %} +Major version of layout engine e.g. 53 +{% enddocs %} + + +{% docs col_operating_system_class %} +Class of the OS e.g. Mobile +{% enddocs %} + + +{% docs col_operating_system_name %} +Name of the OS e.g. Android +{% enddocs %} + + +{% docs col_operating_system_name_version %} +Name and version of the OS e.g. Android 7.0 +{% enddocs %} + + +{% docs col_operating_system_version %} +Version of the OS e.g. 7.0 +{% enddocs %} + + +{% docs col_model_tstamp %} +The current timestamp when the model processed this row. +{% enddocs %} + +{% docs col_ecommerce_user_id %} +The ecommerce user id extracted from the ecommerce user context. +{% enddocs %} + +{% docs col_ecommerce_user_email %} +The ecommerce user email, extracted from the ecommerce user context. +{% enddocs %} + +{% docs col_ecommerce_user_is_guest %} +A boolean extracted from the ecommerce user context to ascertain whether a user is a guest or not. +{% enddocs %} + +{% docs col_checkout_step_number %} +The checkout step index e.g. 1 +{% enddocs %} + +{% docs col_checkout_account_type %} +The type of account that is conducting the checkout e.g. guest +{% enddocs %} + +{% docs col_checkout_billing_full_address %} +The full billing address provided at the checkout step e.g. 1 Lincoln Street +{% enddocs %} + +{% docs col_checkout_billing_postcode %} +The full billing postcode/zipcode provided at the checkout step e.g. 90210 +{% enddocs %} + +{% docs col_checkout_coupon_code %} +The coupon code used at the checkout step e.g. SNOWPLOW50 +{% enddocs %} + +{% docs col_checkout_delivery_method %} +The delivery method selected at the checkout step e.g. Store pickup +{% enddocs %} + +{% docs col_checkout_delivery_provider %} +The delivery provider selected at the checkout step e.g. SantaPost +{% enddocs %} + +{% docs col_checkout_marketing_opt_in %} +A boolean to describe whether or not the user has opted in for marketing emails at the checkout step +{% enddocs %} + +{% docs col_checkout_payment_method %} +The chosen payment method selected at the checkout step e.g. Credit Card +{% enddocs %} + +{% docs col_checkout_proof_of_payment %} +The proof of payment given at the checkout step, e.g. invoice or receipt +{% enddocs %} + +{% docs col_checkout_shipping_full_address %} +Full shipping address +{% enddocs %} + +{% docs col_checkout_shipping_postcode %} +Shipping address postcode +{% enddocs %} + +{% docs col_ecommerce_page_type %} +The type of the page that was visited E.g. homepage, product page, checkout page +{% enddocs %} + +{% docs col_ecommerce_page_language %} +The language that the web page is based in +{% enddocs %} + +{% docs col_ecommerce_page_locale %} +The locale version of the site that is running +{% enddocs %} + +{% docs col_transaction_id %} +The ID of the transaction +{% enddocs %} + +{% docs col_transaction_currency %} +The currency used for the transaction (ISO 4217). +{% enddocs %} + +{% docs col_transaction_payment_method %} +The payment method used for the transaction. +{% enddocs %} + +{% docs col_transaction_revenue %} +The revenue of the transaction. +{% enddocs %} + +{% docs col_transaction_total_quantity %} +Total quantity of items in the transaction. +{% enddocs %} + +{% docs col_transaction_credit_order %} +Whether the transaction is a credit order or not. +{% enddocs %} + +{% docs col_transaction_discount_amount %} +Discount amount taken off +{% enddocs %} + +{% docs col_transaction_discount_code %} +Discount code used. +{% enddocs %} + +{% docs col_transaction_shipping %} +Total cost of shipping on the transaction. +{% enddocs %} + +{% docs col_transaction_tax %} +Total amount of tax on the transaction. +{% enddocs %} + +{% docs col_cart_id %} +The unique ID representing this cart e.g. abc123 +{% enddocs %} + +{% docs col_cart_currency %} +The currency used for this cart (ISO 4217) +{% enddocs %} + +{% docs col_cart_total_value %} +The total value of the cart after this interaction +{% enddocs %} + +{% docs col_ecommerce_action_type %} +The type of ecommerce action that was performed, e.g. transaction, add_to_cart, etc. +{% enddocs %} + +{% docs col_ecommerce_action_name %} +The name that is associated with the ecommerce action. E.g. when a list_click occurs, the name of the product list such as 'recommended' or 'shop the look' +{% enddocs %} + +{% docs col_event_in_session_index %} +The index of the event in the corresponding session. +{% enddocs %} + +{% docs col_derived_tstamp_date %} +Date value of the timestamp making allowance for innaccurate device clock e.g. ‘2013-11-26 00:02:04’ +{% enddocs %} + +{% docs col_cart_created %} +A boolean to describe whether the cart was created in this action +{% enddocs %} + +{% docs col_cart_emptied %} +A boolean to describe whether the cart was emptied in this action +{% enddocs %} + +{% docs col_cart_transacted %} +A boolean to describe whether the cart was transacted (purchased) in this action +{% enddocs %} + +{% docs col_session_entered_at_step %} +A boolean to describe whether the session was entered at this checkout step +{% enddocs %} + +{% docs col_session_entered_at_checkout %} +A boolean to describe whether the session started within the checkout +{% enddocs %} + +{% docs col_session_cart_abandoned %} +A boolean to describe whether the session's cart was abandoned +{% enddocs %} + +{% docs col_checkout_succeeded %} +A boolean to describe whether the checkout succeeded +{% enddocs %} + +{% docs col_product_event_id %} +A surrogate key which is a combination of `product_id` and `event_id` +{% enddocs %} + +{% docs col_product_subcategory %} +The subcategories derived from the defined product category using a user-defined separator +{% enddocs %} + +{% docs col_is_product_view %} +A boolean to describe whether this product interaction was a product view +{% enddocs %} + +{% docs col_is_add_to_cart %} +A boolean to describe whether this product interaction was an add to cart action +{% enddocs %} + +{% docs col_is_remove_from_cart %} +A boolean to describe whether this product interaction was a remove from cart action +{% enddocs %} + +{% docs col_product_list_name %} +The name of the list presented to the user E.g. product list, search results, shop the look, frequently bought with. +{% enddocs %} + +{% docs col_is_product_transaction %} +A boolean to describe whether this product interaction was a transaction (purchase) interaction +{% enddocs %} + +{% docs col_product_id %} +The SKU or product ID. +{% enddocs %} + +{% docs col_product_category %} +The category the product belongs to. Use a consistent separator to express multiple levels. E.g. Woman/Shoes/Sneakers +{% enddocs %} + +{% docs col_product_currency %} +The currency in which the product is being priced (ISO 4217). +{% enddocs %} + +{% docs col_product_price %} +The price of the product at the current time. +{% enddocs %} + +{% docs col_product_brand %} +The brand of the product. +{% enddocs %} + +{% docs col_product_creative_id %} +Identifier/Name/Url for the creative presented on a list or product view. +{% enddocs %} + +{% docs col_product_inventory_status %} +The inventory status of the product E.g. in stock, out of stock, preorder, backorder. +{% enddocs %} + +{% docs col_product_list_price %} +The list or recommended retail price of a product. +{% enddocs %} + +{% docs col_product_name %} +The name or title of the product +{% enddocs %} + +{% docs col_product_list_position %} +The position the product was presented in a list of products E.g. search results, product list page. +{% enddocs %} + +{% docs col_product_quantity %} +The quantity of the product taking part in the ecommerce action. +{% enddocs %} + +{% docs col_product_size %} +The size of the product. +{% enddocs %} + +{% docs col_product_variant %} +The variant of the product. +{% enddocs %} + +{% docs col_product_view_type %} +The type of product view that occurred, e.g. list_view or product_view +{% enddocs %} + +{% docs col_number_products %} +The number of products that are contained in a transaction, counted from the product interactions +{% enddocs %} + +{% docs col_first_cart_created %} +The timestamp of when the session first created a cart +{% enddocs %} + +{% docs col_last_cart_created %} +The timestamp of when the session last created a cart +{% enddocs %} + +{% docs col_first_cart_transacted %} +The timestamp of when the session first transacted (purchased) the contents of a cart +{% enddocs %} + +{% docs col_last_cart_transacted %} +The timestamp of when the session last transacted (purchased) the contents of a cart +{% enddocs %} + +{% docs col_first_checkout_attempted %} +The timestamp of when the session first attempted any checkout steps +{% enddocs %} + +{% docs col_last_checkout_attempted %} +The timestamp of when the session last attempted any checkout steps +{% enddocs %} + +{% docs col_first_checkout_succeeded %} +The timestamp of when the session first succeeded in checking out products +{% enddocs %} + +{% docs col_last_checkout_succeeded %} +The timestamp of when the session last succeeded in checking out products +{% enddocs %} + +{% docs col_first_product_view %} +The timestamp of when the session first viewed a product +{% enddocs %} + +{% docs col_last_product_view %} +The timestamp of when the session last viewed a product +{% enddocs %} + +{% docs col_first_product_add_to_cart %} +The timestamp of when the session first added a product to their cart +{% enddocs %} + +{% docs col_last_product_add_to_cart %} +The timestamp of when the session last added a product to their cart +{% enddocs %} + +{% docs col_first_product_remove_from_cart %} +The timestamp of when the session first removed a product from their cart +{% enddocs %} + +{% docs col_last_product_remove_from_cart %} +The timestamp of when the session last removed a product from their cart +{% enddocs %} + +{% docs col_first_product_transaction %} +The timestamp of when the session first purchased a product +{% enddocs %} + +{% docs col_last_product_transaction %} +The timestamp of when the session last purchased a product +{% enddocs %} + +{% docs col_number_product_views %} +The number of product views that occurred within a session +{% enddocs %} + +{% docs col_number_distinct_products_viewed %} +The number of distinct product IDs that were viewed within a session +{% enddocs %} + +{% docs col_number_add_to_carts %} +The number of add to cart actions that occurred within a session +{% enddocs %} + +{% docs col_number_remove_from_carts %} +The number of remove from cart actions that occurred within a session +{% enddocs %} + +{% docs col_number_product_transactions %} +The number of product transaction actions that occurred within a session +{% enddocs %} + +{% docs col_first_transaction_completed %} +The timestamp of when the session first completed a transaction +{% enddocs %} + +{% docs col_last_transaction_completed %} +The timestamp of when the session last completed a transaction +{% enddocs %} + +{% docs col_total_transaction_revenue %} +The total amount of revenue coming from transactions over the session's lifetime +{% enddocs %} + +{% docs col_total_transaction_quantity %} +The total quantity of products coming from transactions over the session's lifetime +{% enddocs %} + +{% docs col_total_number_transactions %} +The total number of transactions over the session's lifetime +{% enddocs %} + +{% docs col_total_transacted_products %} +The total number of transacted products over the session's lifetime +{% enddocs %} + +{% docs col_number_unique_cart_ids %} +The total number of unique `cart_id`s over the session's lifetime +{% enddocs %} + +{% docs col_number_carts_created %} +The total number of carts created over the session's lifetime +{% enddocs %} + +{% docs col_number_carts_emptied %} +The total number of carts emptied over the session's lifetime +{% enddocs %} + +{% docs col_number_carts_transacted %} +The total number of carts transacted over the session's lifetime +{% enddocs %} + +{% docs col_number_unique_checkout_steps_attempted %} +The total distinct number of checkout steps that a session went through +{% enddocs %} + +{% docs col_number_checkout_steps_visited %} +The total number of (non-unique) checkout steps that a session went through +{% enddocs %} diff --git a/docs/markdown/snowplow_media_player_model_docs.md b/docs/markdown/snowplow_media_player_model_docs.md index 712044a..48f942e 100644 --- a/docs/markdown/snowplow_media_player_model_docs.md +++ b/docs/markdown/snowplow_media_player_model_docs.md @@ -11,7 +11,7 @@ This derived table aggregates media player interactions to a pageview level incr {% enddocs %} {% docs table_plays_by_pageview %} -This view removes impressions from the derived snowplow_media_base table for showing pageview level media play events. +This view removes impressions from the derived snowplow_media_player_base table for showing pageview level media play events. {% enddocs %} {% docs table_session_stats %} diff --git a/integration_tests/data/expected/postgres/snowplow_media_player_media_stats_expected.csv b/integration_tests/data/expected/postgres/snowplow_media_player_media_stats_expected.csv index a576bf2..e3d2428 100644 --- a/integration_tests/data/expected/postgres/snowplow_media_player_media_stats_expected.csv +++ b/integration_tests/data/expected/postgres/snowplow_media_player_media_stats_expected.csv @@ -1,4 +1,4 @@ "media_id","media_label","duration","media_type","media_player_type","play_time_min","avg_play_time_min","first_play","last_play","plays","valid_plays","complete_plays","impressions","avg_playback_rate","play_rate","completion_rate_by_plays","avg_percent_played","avg_retention_rate","last_base_tstamp","_10_percent_reached","_25_percent_reached","_50_percent_reached","_75_percent_reached","_100_percent_reached" html-dbt,dbt Coalesce 2021 - Data modeling at Scale,1887.0,video,org.whatwg-media_element,39.333333333333336,9.833333333333332,2022-01-18 11:56:27.815,2022-01-18 12:11:12.690,4,2,1,4,1.0,1.0,0.25,0.3126656067832538,0.25,2022-01-20 19:13:21.293,1,1,1,1,2 yt-dbt-coalesce-2021,dbt Coalesce 2021 - Data modeling at Scale,1887.0,video,com.youtube-youtube,55.06666666666667,1.4882882882882882,2022-01-18 21:23:57.381,2022-01-20 19:13:21.293,37,5,0,39,1.0270270270270272,0.9487179487179487,0.0,0.04732236210773571,0.002702702702702702,2022-01-20 19:13:21.293,2,2,1,0,4 -yt-dbt-coalesce-2022,dbt Coalesce 2022 - Data modeling at Scale 2,1889.0,video,com.youtube-youtube,,,2999-01-01 00:00:00.000,2000-01-01 00:00:00.000,0,0,0,1,2.0,,,,,2022-01-20 19:17:13.125,0,0,0,0,0 +yt-dbt-coalesce-2022,dbt Coalesce 2022 - Data modeling at Scale 2,1889.0,video,com.youtube-youtube,,,,,0,0,0,1,2.0,,,,,2022-01-20 19:17:13.125,0,0,0,0,0 diff --git a/integration_tests/data/source/snowplow_media_player_context.csv b/integration_tests/data/source/com_snowplowanalytics_snowplow_media_player_1.csv similarity index 100% rename from integration_tests/data/source/snowplow_media_player_context.csv rename to integration_tests/data/source/com_snowplowanalytics_snowplow_media_player_1.csv diff --git a/integration_tests/data/source/snowplow_media_player_event_context.csv b/integration_tests/data/source/com_snowplowanalytics_snowplow_media_player_event_1.csv similarity index 100% rename from integration_tests/data/source/snowplow_media_player_event_context.csv rename to integration_tests/data/source/com_snowplowanalytics_snowplow_media_player_event_1.csv diff --git a/integration_tests/data/source/com_snowplowanalytics_snowplow_web_page_1.csv b/integration_tests/data/source/com_snowplowanalytics_snowplow_web_page_1.csv new file mode 100644 index 0000000..a70b52a --- /dev/null +++ b/integration_tests/data/source/com_snowplowanalytics_snowplow_web_page_1.csv @@ -0,0 +1,249 @@ +event_id,schema_vendor,schema_name,schema_format,schema_versions,root_id,root_tstamp,ref_root,ref_tree,ref_parent,id +afa90542-3892-4101-ae28-74643ba63af6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,afa90542-3892-4101-ae28-74643ba63af6,2022-01-19 10:44:53.883,events,"[""events"",""web_page""]",events,de1bb2e7-60f2-447d-9101-3cc1441cbae8 +9a13d3ae-f77b-49ec-b739-2871e07fef69,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,9a13d3ae-f77b-49ec-b739-2871e07fef69,2022-01-19 10:48:17.165,events,"[""events"",""web_page""]",events,2e929bca-5f31-451f-81d8-6012fa2f245d +60ca10a5-ce28-4d69-8f36-55bf18e99b4c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,60ca10a5-ce28-4d69-8f36-55bf18e99b4c,2022-01-18 21:26:19.693,events,"[""events"",""web_page""]",events,6d9ede59-9ae5-42ca-8ee0-8ea95399292a +3920fabf-5783-4906-9cfa-1b1b8202505c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3920fabf-5783-4906-9cfa-1b1b8202505c,2022-01-20 16:28:50.211,events,"[""events"",""web_page""]",events,fa0b5633-9873-422a-a507-de16e58a4c91 +68e61b7c-3f92-4712-8e99-88baf593f043,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,68e61b7c-3f92-4712-8e99-88baf593f043,2022-01-20 16:26:20.612,events,"[""events"",""web_page""]",events,d50ad9de-1c4c-45ca-9368-230e5608b766 +b1b3c861-a9d6-4637-9635-476f71b228db,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b1b3c861-a9d6-4637-9635-476f71b228db,2022-01-20 15:49:55.097,events,"[""events"",""web_page""]",events,42b39f17-3ca4-4159-b659-bc55e5cef9c4 +fe3d6804-72e9-48f2-88dc-cb27dd053597,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fe3d6804-72e9-48f2-88dc-cb27dd053597,2022-01-18 21:32:35.473,events,"[""events"",""web_page""]",events,cb828868-c85a-448d-8cd0-3aa8ef1d7d97 +c1060353-ba40-4d56-8c57-26e4584cc7bd,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c1060353-ba40-4d56-8c57-26e4584cc7bd,2022-01-18 21:25:03.097,events,"[""events"",""web_page""]",events,87c8e627-6145-425b-ad28-7e120fa11f9f +03e62db3-52f3-40fa-a76b-c83d25ae1f62,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,03e62db3-52f3-40fa-a76b-c83d25ae1f62,2022-01-18 21:23:57.481,events,"[""events"",""web_page""]",events,231fb32c-5e81-4327-8ce2-a506962df8e0 +ad5b95ab-c4e0-44da-926d-2f3c2f93d949,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ad5b95ab-c4e0-44da-926d-2f3c2f93d949,2022-01-19 11:38:32.126,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +baa0ecfb-e722-498b-9c17-4c45772080ca,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,baa0ecfb-e722-498b-9c17-4c45772080ca,2022-01-20 16:23:30.732,events,"[""events"",""web_page""]",events,650605c8-94b0-4d55-8b7b-90e135832dc4 +a931fde5-84e7-45db-a653-5d90186e898b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a931fde5-84e7-45db-a653-5d90186e898b,2022-01-19 11:09:42.442,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +39dd1ee2-0dfc-45ae-a885-0fe216c6357f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,39dd1ee2-0dfc-45ae-a885-0fe216c6357f,2022-01-20 19:07:20.214,events,"[""events"",""web_page""]",events,6affcf25-3d83-4d1c-8e6b-85c9b9a1c132 +57748c5a-1d2d-43fd-a71f-93cb8dc8b50f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,57748c5a-1d2d-43fd-a71f-93cb8dc8b50f,2022-01-18 21:36:51.831,events,"[""events"",""web_page""]",events,b0e8ef14-fbef-435c-a198-f6102865fc7a +bf498ecd-1385-41f1-adb9-671321c6fb22,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,bf498ecd-1385-41f1-adb9-671321c6fb22,2022-01-19 12:00:21.463,events,"[""events"",""web_page""]",events,32f66f1b-788f-471a-8dc2-132e9f845882 +522f77f0-e157-49bf-a1cd-0411f2b4f390,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,522f77f0-e157-49bf-a1cd-0411f2b4f390,2022-01-19 12:02:03.782,events,"[""events"",""web_page""]",events,2fa2be59-2a56-47c4-9aa9-7cbc2a25dabe +c594dcdf-cb0b-4fcd-8bde-f8fcd93975fe,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c594dcdf-cb0b-4fcd-8bde-f8fcd93975fe,2022-01-20 19:03:16.264,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +fe7f43a3-ce23-4cb8-b37a-754351120f5f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fe7f43a3-ce23-4cb8-b37a-754351120f5f,2022-01-18 21:57:34.831,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +c5708cee-b146-4390-af11-0060335c2341,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c5708cee-b146-4390-af11-0060335c2341,2022-01-20 19:03:00.568,events,"[""events"",""web_page""]",events,db2a44c1-6af4-4be5-bc80-7ff76d72b622 +d4ca2668-744b-4ef2-a2f6-867f61fa7888,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d4ca2668-744b-4ef2-a2f6-867f61fa7888,2022-01-20 16:33:42.535,events,"[""events"",""web_page""]",events,8bc7951b-d444-4179-a69f-45ef6d9e81ba +30c13970-29b6-47a5-b85f-7494571a4064,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,30c13970-29b6-47a5-b85f-7494571a4064,2022-01-20 19:03:44.018,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c79561b1-20eb-4349-a432-54434d3841db,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c79561b1-20eb-4349-a432-54434d3841db,2022-01-20 19:07:00.480,events,"[""events"",""web_page""]",events,1a5bebe2-b26a-439f-b826-02257d351292 +2ae95fd7-f455-4d39-a10b-3acfc4096a8a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2ae95fd7-f455-4d39-a10b-3acfc4096a8a,2022-01-20 19:00:27.828,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c74ba532-37ed-4f9a-95fa-26cf4fc25ea9,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c74ba532-37ed-4f9a-95fa-26cf4fc25ea9,2022-01-19 12:02:48.265,events,"[""events"",""web_page""]",events,8e8967da-859e-4396-9323-2f704ee44955 +52407e9d-a8fb-4b42-97b3-d738b49a49c7,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,52407e9d-a8fb-4b42-97b3-d738b49a49c7,2022-01-20 19:00:27.862,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +2e144b37-68b1-40ce-ba61-abdf17644e1c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2e144b37-68b1-40ce-ba61-abdf17644e1c,2022-01-20 16:25:50.190,events,"[""events"",""web_page""]",events,acb69ffc-3d79-4870-a543-dc7952599720 +d9ef20d9-d673-4965-bd55-f2dd96acef3a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d9ef20d9-d673-4965-bd55-f2dd96acef3a,2022-01-19 07:14:26.775,events,"[""events"",""web_page""]",events,16b7a187-0437-4573-8fbb-e6d9cf1ac171 +71b48b0e-9e8b-4c13-bb49-8c61c88814be,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,71b48b0e-9e8b-4c13-bb49-8c61c88814be,2022-01-18 21:56:20.088,events,"[""events"",""web_page""]",events,17b13c2f-dcaa-48a6-ba8a-f5ca4416059c +6ffb21de-0611-47ba-9f9e-e4d980a77247,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6ffb21de-0611-47ba-9f9e-e4d980a77247,2022-01-20 16:23:43.050,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +ba982c00-ccfd-49b3-8edc-b9f48a5e3f49,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ba982c00-ccfd-49b3-8edc-b9f48a5e3f49,2022-01-18 22:00:21.611,events,"[""events"",""web_page""]",events,83fcb20c-f3cb-4f12-a1b4-9d1c0e086163 +6d3710fe-de6e-4a21-a4d2-0a7c54e47b45,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6d3710fe-de6e-4a21-a4d2-0a7c54e47b45,2022-01-20 19:13:21.477,events,"[""events"",""web_page""]",events,7788ffe1-1b34-418c-a123-e86b1130d0ae +43e2bb23-97ab-4901-8258-11f57303298d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,43e2bb23-97ab-4901-8258-11f57303298d,2022-01-19 11:37:52.398,events,"[""events"",""web_page""]",events,2da9e4d5-fa22-40d5-a391-98f7f15401ca +a07793e5-af88-4ce5-b7d2-c2480b1db027,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a07793e5-af88-4ce5-b7d2-c2480b1db027,2022-01-19 11:17:19.670,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +c1729d49-d766-4225-936e-616e2fb25730,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c1729d49-d766-4225-936e-616e2fb25730,2022-01-20 15:50:04.795,events,"[""events"",""web_page""]",events,734809af-fad3-4c84-a5e0-647a1285655a +dccaeb9e-8a3f-47b3-93df-e4191bc39327,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,dccaeb9e-8a3f-47b3-93df-e4191bc39327,2022-01-18 21:42:19.929,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +4745785f-afd4-4d64-a6c3-cf58a6523786,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4745785f-afd4-4d64-a6c3-cf58a6523786,2022-01-20 19:03:44.503,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +059b5b60-ed30-40b7-ab40-5c50f1e0a716,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,059b5b60-ed30-40b7-ab40-5c50f1e0a716,2022-01-20 19:05:29.038,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +4300702f-e568-407a-91cb-eed013c9bce2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4300702f-e568-407a-91cb-eed013c9bce2,2022-01-18 21:56:31.926,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +ea1af73c-3c93-4a5a-9864-41485760df6a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ea1af73c-3c93-4a5a-9864-41485760df6a,2022-01-18 11:56:33.197,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +3079b8eb-7fc5-40b3-af9e-03fb78ab423c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3079b8eb-7fc5-40b3-af9e-03fb78ab423c,2022-01-18 11:56:28.486,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +b218db0e-f7b6-45a9-93ed-24050446dc69,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b218db0e-f7b6-45a9-93ed-24050446dc69,2022-01-20 16:26:21.194,events,"[""events"",""web_page""]",events,d50ad9de-1c4c-45ca-9368-230e5608b766 +fb7319b7-345c-4b9c-bd53-e998157e2261,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fb7319b7-345c-4b9c-bd53-e998157e2261,2022-01-18 11:59:34.175,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +77522a4d-aa1e-47e0-9285-986cbd3d1234,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,77522a4d-aa1e-47e0-9285-986cbd3d1234,2022-01-18 11:57:21.357,events,"[""events"",""web_page""]",events,7b2539f5-6ea4-4625-81c2-04dc8ee950d6 +a5450ae7-810c-4963-8265-6d5bfe7ad935,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a5450ae7-810c-4963-8265-6d5bfe7ad935,2022-01-18 12:11:12.692,events,"[""events"",""web_page""]",events,70d2839e-c8a6-4cbc-abc5-e1ff763a82b3 +99226fef-58b9-4501-89c5-818d53c50359,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,99226fef-58b9-4501-89c5-818d53c50359,2022-01-18 11:56:27.816,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +b8d2d32a-955f-43a7-a535-1ff247d39547,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b8d2d32a-955f-43a7-a535-1ff247d39547,2022-01-20 16:38:11.111,events,"[""events"",""web_page""]",events,ee89aa81-19f9-4929-a48e-6d881381a161 +3fd881b6-5222-4c50-ba99-7afae429f29b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3fd881b6-5222-4c50-ba99-7afae429f29b,2022-01-20 19:03:00.078,events,"[""events"",""web_page""]",events,db2a44c1-6af4-4be5-bc80-7ff76d72b622 +14377980-3290-40ee-9c07-39fc74264448,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,14377980-3290-40ee-9c07-39fc74264448,2022-01-19 11:17:16.218,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +6401cfc4-eb71-4676-abc0-46f96b7f6aef,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6401cfc4-eb71-4676-abc0-46f96b7f6aef,2022-01-18 21:57:34.391,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +1d641000-fc51-4c1f-85b0-8ca3d2ab2a97,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,1d641000-fc51-4c1f-85b0-8ca3d2ab2a97,2022-01-19 12:02:47.985,events,"[""events"",""web_page""]",events,8e8967da-859e-4396-9323-2f704ee44955 +8601ef5e-ce5b-40c5-ba28-a2b8b0608424,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8601ef5e-ce5b-40c5-ba28-a2b8b0608424,2022-01-20 17:03:14.376,events,"[""events"",""web_page""]",events,9da42b88-c8bf-4c5d-8d1b-985af97f2e10 +54708d57-8923-42e9-bb89-a928315fe394,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,54708d57-8923-42e9-bb89-a928315fe394,2022-01-20 19:00:27.184,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +6b270279-01e3-49c5-96ec-b01a38ceb8a3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6b270279-01e3-49c5-96ec-b01a38ceb8a3,2022-01-20 19:03:16.136,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +d5098028-28f8-485c-add2-e822f9ab0984,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d5098028-28f8-485c-add2-e822f9ab0984,2022-01-19 07:14:26.168,events,"[""events"",""web_page""]",events,16b7a187-0437-4573-8fbb-e6d9cf1ac171 +735a1ed7-af29-48d3-ab24-cb7e5d27bc45,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,735a1ed7-af29-48d3-ab24-cb7e5d27bc45,2022-01-20 19:07:19.691,events,"[""events"",""web_page""]",events,6affcf25-3d83-4d1c-8e6b-85c9b9a1c132 +b88d92a3-964b-42b5-860d-0fc3f0cd1735,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b88d92a3-964b-42b5-860d-0fc3f0cd1735,2022-01-19 11:09:41.820,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +778a2975-07c5-4b01-8c32-c1aa79281a9b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,778a2975-07c5-4b01-8c32-c1aa79281a9b,2022-01-20 19:13:21.296,events,"[""events"",""web_page""]",events,7788ffe1-1b34-418c-a123-e86b1130d0ae +b20cc61b-ecbb-4083-bb22-d26f24146972,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b20cc61b-ecbb-4083-bb22-d26f24146972,2022-01-20 17:03:42.766,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +d4071d01-0d30-4096-a933-887f623d8572,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d4071d01-0d30-4096-a933-887f623d8572,2022-01-20 19:07:00.043,events,"[""events"",""web_page""]",events,1a5bebe2-b26a-439f-b826-02257d351292 +26073371-3ce1-429d-a987-ea10fa2b2c44,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,26073371-3ce1-429d-a987-ea10fa2b2c44,2022-01-20 17:57:07.300,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +68975326-298c-4a32-9824-6e6406eb71ca,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,68975326-298c-4a32-9824-6e6406eb71ca,2022-01-20 19:05:28.833,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c9df5e37-b82b-4d56-8186-f9720c9a4e13,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c9df5e37-b82b-4d56-8186-f9720c9a4e13,2022-01-20 19:03:44.221,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +4ec60b79-e5dd-4f64-ae51-8ba82d0db86c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4ec60b79-e5dd-4f64-ae51-8ba82d0db86c,2022-01-20 15:50:04.540,events,"[""events"",""web_page""]",events,734809af-fad3-4c84-a5e0-647a1285655a +e6a9e9c4-2d72-4c8f-b7a2-612e64cb9223,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e6a9e9c4-2d72-4c8f-b7a2-612e64cb9223,2022-01-18 21:42:19.408,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +c4634f2a-d11a-4b12-b2ab-597a62667f0f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c4634f2a-d11a-4b12-b2ab-597a62667f0f,2022-01-18 21:32:35.035,events,"[""events"",""web_page""]",events,cb828868-c85a-448d-8cd0-3aa8ef1d7d97 +0f767cd9-2bb8-43bb-a7fb-228a14366cf0,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,0f767cd9-2bb8-43bb-a7fb-228a14366cf0,2022-01-18 21:56:31.153,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +6a234b30-2af8-4d6f-9610-ac25416866b0,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6a234b30-2af8-4d6f-9610-ac25416866b0,2022-01-18 21:36:51.465,events,"[""events"",""web_page""]",events,b0e8ef14-fbef-435c-a198-f6102865fc7a +fc4ab3d9-3c2a-47ba-808d-e709c45364f3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fc4ab3d9-3c2a-47ba-808d-e709c45364f3,2022-01-19 12:02:03.252,events,"[""events"",""web_page""]",events,2fa2be59-2a56-47c4-9aa9-7cbc2a25dabe +c37d3505-1c22-46ea-a761-d8e5f87584a2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c37d3505-1c22-46ea-a761-d8e5f87584a2,2022-01-20 15:49:54.695,events,"[""events"",""web_page""]",events,42b39f17-3ca4-4159-b659-bc55e5cef9c4 +3731d5f0-19fc-4654-b5ad-db43dfb34263,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3731d5f0-19fc-4654-b5ad-db43dfb34263,2022-01-20 16:26:20.344,events,"[""events"",""web_page""]",events,d50ad9de-1c4c-45ca-9368-230e5608b766 +07688e73-717b-42e3-b9b5-58241288596b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,07688e73-717b-42e3-b9b5-58241288596b,2022-01-18 21:56:19.969,events,"[""events"",""web_page""]",events,17b13c2f-dcaa-48a6-ba8a-f5ca4416059c +21731d27-415c-4b4d-b06b-a484f20e13c3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,21731d27-415c-4b4d-b06b-a484f20e13c3,2022-01-19 10:44:53.576,events,"[""events"",""web_page""]",events,de1bb2e7-60f2-447d-9101-3cc1441cbae8 +d6944531-418d-44b9-a1bc-dffd47ed11fe,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d6944531-418d-44b9-a1bc-dffd47ed11fe,2022-01-20 16:25:49.827,events,"[""events"",""web_page""]",events,acb69ffc-3d79-4870-a543-dc7952599720 +e51a1ed2-47cc-4fd3-9a86-46fadb9c6c9f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e51a1ed2-47cc-4fd3-9a86-46fadb9c6c9f,2022-01-19 10:48:16.916,events,"[""events"",""web_page""]",events,2e929bca-5f31-451f-81d8-6012fa2f245d +7e7f24d7-fdc0-4073-8201-6636f1b19435,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7e7f24d7-fdc0-4073-8201-6636f1b19435,2022-01-18 22:00:21.297,events,"[""events"",""web_page""]",events,83fcb20c-f3cb-4f12-a1b4-9d1c0e086163 +c5503a02-b251-4a83-a4ca-1174e076f045,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c5503a02-b251-4a83-a4ca-1174e076f045,2022-01-19 12:00:21.208,events,"[""events"",""web_page""]",events,32f66f1b-788f-471a-8dc2-132e9f845882 +a0af0681-7cec-45ea-b414-0291ad5c41fe,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a0af0681-7cec-45ea-b414-0291ad5c41fe,2022-01-20 16:23:30.190,events,"[""events"",""web_page""]",events,650605c8-94b0-4d55-8b7b-90e135832dc4 +02f38921-759e-4283-8b95-325e8da16c93,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,02f38921-759e-4283-8b95-325e8da16c93,2022-01-18 21:25:02.978,events,"[""events"",""web_page""]",events,87c8e627-6145-425b-ad28-7e120fa11f9f +97b2d774-7cab-4acf-875d-d880b605cf3f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,97b2d774-7cab-4acf-875d-d880b605cf3f,2022-01-18 21:26:19.573,events,"[""events"",""web_page""]",events,6d9ede59-9ae5-42ca-8ee0-8ea95399292a +b187f747-0fc6-499e-a804-8b5dc27d1fc1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b187f747-0fc6-499e-a804-8b5dc27d1fc1,2022-01-20 16:23:42.746,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +a1691fc3-34d1-4515-9bad-884bd714d3bd,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a1691fc3-34d1-4515-9bad-884bd714d3bd,2022-01-20 16:33:41.700,events,"[""events"",""web_page""]",events,8bc7951b-d444-4179-a69f-45ef6d9e81ba +fad4a659-7b3a-4a87-bcde-7c2f50658a80,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fad4a659-7b3a-4a87-bcde-7c2f50658a80,2022-01-18 21:23:57.381,events,"[""events"",""web_page""]",events,231fb32c-5e81-4327-8ce2-a506962df8e0 +8869854f-4fcb-4f41-802f-7b7cae0acdd3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8869854f-4fcb-4f41-802f-7b7cae0acdd3,2022-01-19 11:37:52.398,events,"[""events"",""web_page""]",events,2da9e4d5-fa22-40d5-a391-98f7f15401ca +a79cc8cc-0129-4fa2-b11d-a75898b4ec33,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a79cc8cc-0129-4fa2-b11d-a75898b4ec33,2022-01-19 11:38:31.938,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +12ec4305-6f91-4d96-a4da-a77a60ba1631,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,12ec4305-6f91-4d96-a4da-a77a60ba1631,2022-01-20 16:28:49.610,events,"[""events"",""web_page""]",events,fa0b5633-9873-422a-a507-de16e58a4c91 +46882063-666f-4264-bafd-6be9c37862d9,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,46882063-666f-4264-bafd-6be9c37862d9,2022-01-18 11:57:22.505,events,"[""events"",""web_page""]",events,7b2539f5-6ea4-4625-81c2-04dc8ee950d6 +8ea36beb-3af1-445b-be36-e7bea13e101e,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8ea36beb-3af1-445b-be36-e7bea13e101e,2022-01-19 10:44:55.099,events,"[""events"",""web_page""]",events,de1bb2e7-60f2-447d-9101-3cc1441cbae8 +598746c4-e436-4726-804f-66217d51a271,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,598746c4-e436-4726-804f-66217d51a271,2022-01-20 19:07:21.683,events,"[""events"",""web_page""]",events,6affcf25-3d83-4d1c-8e6b-85c9b9a1c132 +870ed756-d5a8-45a5-9f27-8d540508338d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,870ed756-d5a8-45a5-9f27-8d540508338d,2022-01-18 12:11:14.211,events,"[""events"",""web_page""]",events,70d2839e-c8a6-4cbc-abc5-e1ff763a82b3 +6b596704-d385-4d2d-ab4c-8d44211d9bb6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6b596704-d385-4d2d-ab4c-8d44211d9bb6,2022-01-19 12:02:05.527,events,"[""events"",""web_page""]",events,2fa2be59-2a56-47c4-9aa9-7cbc2a25dabe +7e07b094-6718-4311-bb16-db01631dcc43,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7e07b094-6718-4311-bb16-db01631dcc43,2022-01-19 12:02:13.912,events,"[""events"",""web_page""]",events,2fa2be59-2a56-47c4-9aa9-7cbc2a25dabe +da104488-05cd-4b0f-bfef-f8d3b37da30b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,da104488-05cd-4b0f-bfef-f8d3b37da30b,2022-01-20 15:50:06.227,events,"[""events"",""web_page""]",events,734809af-fad3-4c84-a5e0-647a1285655a +d818a079-f38e-41f5-bb8c-0a14d75f50d1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d818a079-f38e-41f5-bb8c-0a14d75f50d1,2022-01-20 16:33:43.902,events,"[""events"",""web_page""]",events,8bc7951b-d444-4179-a69f-45ef6d9e81ba +a3d81961-d038-4cae-aab8-5d881883cf6c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a3d81961-d038-4cae-aab8-5d881883cf6c,2022-01-19 12:00:22.965,events,"[""events"",""web_page""]",events,32f66f1b-788f-471a-8dc2-132e9f845882 +e1458bf9-decc-453f-85cf-894ee3d77076,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e1458bf9-decc-453f-85cf-894ee3d77076,2022-01-20 15:49:56.589,events,"[""events"",""web_page""]",events,42b39f17-3ca4-4159-b659-bc55e5cef9c4 +77f8401a-57b0-4df2-bbdc-04983e9c4e48,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,77f8401a-57b0-4df2-bbdc-04983e9c4e48,2022-01-20 16:23:44.583,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +01cae27c-4b41-49c7-a5c4-2b3723800d22,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,01cae27c-4b41-49c7-a5c4-2b3723800d22,2022-01-20 15:49:58.734,events,"[""events"",""web_page""]",events,42b39f17-3ca4-4159-b659-bc55e5cef9c4 +e9775e7f-af1f-47ad-af03-d0b53276fd20,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e9775e7f-af1f-47ad-af03-d0b53276fd20,2022-01-19 10:48:18.889,events,"[""events"",""web_page""]",events,2e929bca-5f31-451f-81d8-6012fa2f245d +7e927a88-e744-4af7-b81c-32f02ec675f6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7e927a88-e744-4af7-b81c-32f02ec675f6,2022-01-20 17:57:08.082,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +c4260885-0afe-43e2-92bf-3fc435929dca,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c4260885-0afe-43e2-92bf-3fc435929dca,2022-01-20 17:57:07.883,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +6129ae9a-6054-4c87-95e8-af84d770e5f5,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6129ae9a-6054-4c87-95e8-af84d770e5f5,2022-01-20 17:57:09.158,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +b0881a0a-fc74-4e41-b4b1-b0edd4415711,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b0881a0a-fc74-4e41-b4b1-b0edd4415711,2022-01-20 17:57:15.119,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +06bfcbac-9054-4e78-a8e9-be3c8cff9cd2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,06bfcbac-9054-4e78-a8e9-be3c8cff9cd2,2022-01-20 17:57:15.865,events,"[""events"",""web_page""]",events,0b31039f-7f2e-44e4-a940-88ba590f9a64 +a89f8410-dde0-4464-a4ce-7fcf9a2ee8d7,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a89f8410-dde0-4464-a4ce-7fcf9a2ee8d7,2022-01-18 12:19:42.433,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +7653b42f-a1c6-41b5-b74f-d640a81e8723,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7653b42f-a1c6-41b5-b74f-d640a81e8723,2022-01-18 12:19:43.459,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +db9a4d95-66b7-4711-b202-5c09052ffb46,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,db9a4d95-66b7-4711-b202-5c09052ffb46,2022-01-20 20:44:54.824,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +e7881c2d-6b63-49c8-a7dc-35dc10a14318,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e7881c2d-6b63-49c8-a7dc-35dc10a14318,2022-01-20 20:45:02.413,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +437b2ceb-1cff-461a-96e5-c18d40b00e14,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,437b2ceb-1cff-461a-96e5-c18d40b00e14,2022-01-20 20:45:11.975,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +c4492ea6-1f1a-42cb-a5c8-1b7eee29a4c5,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c4492ea6-1f1a-42cb-a5c8-1b7eee29a4c5,2022-01-18 21:24:10.719,events,"[""events"",""web_page""]",events,231fb32c-5e81-4327-8ce2-a506962df8e0 +844d3b63-7254-45a9-8c96-d34d6aa49513,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,844d3b63-7254-45a9-8c96-d34d6aa49513,2022-01-18 21:24:29.616,events,"[""events"",""web_page""]",events,231fb32c-5e81-4327-8ce2-a506962df8e0 +64f53574-e9d3-4dca-a160-cc1e970487e6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,64f53574-e9d3-4dca-a160-cc1e970487e6,2022-01-20 19:00:41.664,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +66992e4c-a069-40c2-b5be-4934064d23ca,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,66992e4c-a069-40c2-b5be-4934064d23ca,2022-01-20 19:00:49.897,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +0aa8541e-aa3f-4ac8-a08a-f0ce94162529,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,0aa8541e-aa3f-4ac8-a08a-f0ce94162529,2022-01-18 12:23:09.784,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +826e4264-4b65-4c1d-83a5-b64fe38add34,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,826e4264-4b65-4c1d-83a5-b64fe38add34,2022-01-18 12:24:34.516,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +6ec16379-69e4-4c44-9c98-5f5f2c0525e1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6ec16379-69e4-4c44-9c98-5f5f2c0525e1,2022-01-18 12:24:40.075,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +af84764a-2a70-4404-aab2-1086b851d18f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,af84764a-2a70-4404-aab2-1086b851d18f,2022-01-18 12:26:53.427,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +36d5d727-548f-49d3-b390-9836cce7bc6b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,36d5d727-548f-49d3-b390-9836cce7bc6b,2022-01-18 12:28:03.438,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +7f060250-f097-46fa-94c2-dfcb3d88adc4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7f060250-f097-46fa-94c2-dfcb3d88adc4,2022-01-20 19:01:19.576,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +790d0e9f-d7c5-4968-9f01-a9642efa7e60,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,790d0e9f-d7c5-4968-9f01-a9642efa7e60,2022-01-20 19:01:20.134,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +4ad67e1f-5517-45fb-bd27-00dbe42d61de,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4ad67e1f-5517-45fb-bd27-00dbe42d61de,2022-01-18 12:11:34.317,events,"[""events"",""web_page""]",events,70d2839e-c8a6-4cbc-abc5-e1ff763a82b3 +a7de570a-f37d-4563-9d79-acd4a6d4d636,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a7de570a-f37d-4563-9d79-acd4a6d4d636,2022-01-18 12:11:26.188,events,"[""events"",""web_page""]",events,70d2839e-c8a6-4cbc-abc5-e1ff763a82b3 +33f6f631-8c79-406d-8cab-a9bfdb2163b0,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,33f6f631-8c79-406d-8cab-a9bfdb2163b0,2022-01-18 12:11:30.959,events,"[""events"",""web_page""]",events,70d2839e-c8a6-4cbc-abc5-e1ff763a82b3 +73c30284-abb5-4db4-a86b-0d323867091f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,73c30284-abb5-4db4-a86b-0d323867091f,2022-01-20 19:01:45.378,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +f108c2a0-91c6-449f-90fb-7593943004aa,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,f108c2a0-91c6-449f-90fb-7593943004aa,2022-01-20 19:02:04.536,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c7d75d78-8bb1-4be2-b58e-154a4fd0454f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c7d75d78-8bb1-4be2-b58e-154a4fd0454f,2022-01-20 19:02:04.149,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +778e10bc-a86b-4a10-910e-e73c7af9e49f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,778e10bc-a86b-4a10-910e-e73c7af9e49f,2022-01-20 19:02:18.223,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +1dfe4f9d-b5d5-4281-82aa-9a389681b5dc,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,1dfe4f9d-b5d5-4281-82aa-9a389681b5dc,2022-01-18 11:59:53.385,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +508a04d4-ff7b-4e46-b220-e5ec17df77f8,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,508a04d4-ff7b-4e46-b220-e5ec17df77f8,2022-01-20 19:01:11.044,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +06a84b52-159f-4661-b1b1-4446671d2837,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,06a84b52-159f-4661-b1b1-4446671d2837,2022-01-20 19:01:10.571,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +75081f7c-907e-409d-ad6b-4e28261599ee,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,75081f7c-907e-409d-ad6b-4e28261599ee,2022-01-20 19:01:03.379,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +074d1622-3703-484d-83d2-404be161866b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,074d1622-3703-484d-83d2-404be161866b,2022-01-20 19:01:04.021,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +8b10f64b-f71d-41cb-ad93-f75bc88f7fd8,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8b10f64b-f71d-41cb-ad93-f75bc88f7fd8,2022-01-20 19:01:04.272,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +62803a70-12fd-4fc6-abde-071f79c56370,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,62803a70-12fd-4fc6-abde-071f79c56370,2022-01-18 12:31:11.295,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +be8fda47-0a3e-4b59-befc-7918bf6fb92a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,be8fda47-0a3e-4b59-befc-7918bf6fb92a,2022-01-18 12:31:36.248,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +f4eb722d-c953-4677-a3c0-01ad247577a9,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,f4eb722d-c953-4677-a3c0-01ad247577a9,2022-01-18 21:54:20.233,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +68795759-74e4-4cda-af0c-6e84587cbf43,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,68795759-74e4-4cda-af0c-6e84587cbf43,2022-01-18 21:54:20.310,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +2aff336c-34fa-4c92-ab56-107d3692d041,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2aff336c-34fa-4c92-ab56-107d3692d041,2022-01-20 19:02:19.630,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c64b5c01-cdda-429e-a4d3-bba98126a789,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c64b5c01-cdda-429e-a4d3-bba98126a789,2022-01-20 19:02:19.881,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +748dbfd2-895d-40ce-8d4e-a92f16bd2bb4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,748dbfd2-895d-40ce-8d4e-a92f16bd2bb4,2022-01-18 21:54:20.363,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +64358b0c-f132-488b-b1d7-1a28271eb4d8,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,64358b0c-f132-488b-b1d7-1a28271eb4d8,2022-01-18 21:54:21.378,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +20ac2fd8-cdd5-4275-ab06-4bb376d4a441,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,20ac2fd8-cdd5-4275-ab06-4bb376d4a441,2022-01-18 21:56:39.426,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +55ba8779-e461-44b0-9642-b7a92beb809d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,55ba8779-e461-44b0-9642-b7a92beb809d,2022-01-18 21:56:39.643,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +840f7246-1561-4cb8-97e1-237ea2ddc5d1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,840f7246-1561-4cb8-97e1-237ea2ddc5d1,2022-01-18 21:56:40.303,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +21e0dfc8-4d71-481b-adeb-81d1e5594753,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,21e0dfc8-4d71-481b-adeb-81d1e5594753,2022-01-18 21:56:40.764,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +19581463-0d5d-49c8-adb4-8fd02d830c4b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,19581463-0d5d-49c8-adb4-8fd02d830c4b,2022-01-18 21:45:28.580,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +c53c8773-2344-4d29-aee2-cc2c2efc7602,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c53c8773-2344-4d29-aee2-cc2c2efc7602,2022-01-18 11:56:36.641,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +d73d0944-aaee-4ad9-a5f9-8bf609e92f4f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d73d0944-aaee-4ad9-a5f9-8bf609e92f4f,2022-01-18 11:56:37.512,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +342fe887-d863-4744-9ff1-d93c46ab970b,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,342fe887-d863-4744-9ff1-d93c46ab970b,2022-01-18 21:57:53.351,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +a1bffcb7-7046-4935-a989-ceb4c441a628,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a1bffcb7-7046-4935-a989-ceb4c441a628,2022-01-18 21:57:52.865,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +8fa9c24f-95e0-4b2a-ac92-bccf07b1e276,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8fa9c24f-95e0-4b2a-ac92-bccf07b1e276,2022-01-18 21:57:53.704,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +76db08cd-a516-479e-b494-c1971b92c046,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,76db08cd-a516-479e-b494-c1971b92c046,2022-01-18 12:32:43.445,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +b9b797e4-38d9-4509-9ca0-02ff445e8fb1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b9b797e4-38d9-4509-9ca0-02ff445e8fb1,2022-01-18 12:32:43.368,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +f0f0ea28-ba90-44c2-9b78-6f76531ecd18,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,f0f0ea28-ba90-44c2-9b78-6f76531ecd18,2022-01-18 11:56:42.273,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +5bf9d85b-0c1b-487d-a425-d84134e5294a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5bf9d85b-0c1b-487d-a425-d84134e5294a,2022-01-18 11:56:42.223,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +5fb78d01-9a4e-45ff-bb51-04ff9e9f820c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5fb78d01-9a4e-45ff-bb51-04ff9e9f820c,2022-01-18 21:57:57.090,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +5dd91b0d-5ae1-44fa-b244-d1ae29200243,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5dd91b0d-5ae1-44fa-b244-d1ae29200243,2022-01-18 21:55:06.686,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +5ad5798d-4ca9-4966-9c2c-5aee352499d7,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5ad5798d-4ca9-4966-9c2c-5aee352499d7,2022-01-18 21:57:03.174,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +9e2df242-f585-4c1b-9d6f-3eb661b1f83a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,9e2df242-f585-4c1b-9d6f-3eb661b1f83a,2022-01-20 19:02:44.480,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +7da4048a-3dd1-4a80-bdf3-485c44b9cfdb,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7da4048a-3dd1-4a80-bdf3-485c44b9cfdb,2022-01-18 12:02:44.097,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +43f1c370-bd9b-444c-926a-a6d593f1ab6c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,43f1c370-bd9b-444c-926a-a6d593f1ab6c,2022-01-19 11:41:42.483,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +abb2f67e-07d9-41e7-91e2-77f18f026bed,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,abb2f67e-07d9-41e7-91e2-77f18f026bed,2022-01-19 11:41:42.529,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +d81f0ec9-beaf-4c59-ab79-07e1f5aacaa1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d81f0ec9-beaf-4c59-ab79-07e1f5aacaa1,2022-01-19 11:17:22.069,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +c2c92b55-c834-4992-b186-36ab5dedb534,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c2c92b55-c834-4992-b186-36ab5dedb534,2022-01-19 11:17:26.188,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +210f1887-1e0f-4f13-b806-258315c4bcbd,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,210f1887-1e0f-4f13-b806-258315c4bcbd,2022-01-18 11:59:55.391,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +241a4089-33e9-4366-bc7d-a7666bdb3c6e,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,241a4089-33e9-4366-bc7d-a7666bdb3c6e,2022-01-18 11:59:56.211,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +9346c2eb-6651-4a0d-9c23-b3069c3f51d1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,9346c2eb-6651-4a0d-9c23-b3069c3f51d1,2022-01-18 21:46:00.694,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +7679f23d-f8b2-4c1a-b166-13670f0e6347,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7679f23d-f8b2-4c1a-b166-13670f0e6347,2022-01-18 11:56:35.017,events,"[""events"",""web_page""]",events,ffae6eef-c255-4dea-918f-f793c716e117 +7133009e-24e8-43d1-9709-c7aefd7adf88,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7133009e-24e8-43d1-9709-c7aefd7adf88,2022-01-18 21:46:20.697,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +ebf78642-101e-4e49-9016-0a928ea6bbf7,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ebf78642-101e-4e49-9016-0a928ea6bbf7,2022-01-19 07:14:54.949,events,"[""events"",""web_page""]",events,16b7a187-0437-4573-8fbb-e6d9cf1ac171 +d7b42126-c41d-4c07-9ee2-592bcbec4772,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d7b42126-c41d-4c07-9ee2-592bcbec4772,2022-01-19 07:14:59.462,events,"[""events"",""web_page""]",events,16b7a187-0437-4573-8fbb-e6d9cf1ac171 +deb2e3fc-80c7-4cc5-a438-90b67c89f579,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,deb2e3fc-80c7-4cc5-a438-90b67c89f579,2022-01-19 11:17:26.976,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +4dbe6068-edbe-441e-8f1c-21d21fa7a17f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4dbe6068-edbe-441e-8f1c-21d21fa7a17f,2022-01-19 11:17:45.496,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +44394156-c93b-4354-87df-eaaed846e9c8,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,44394156-c93b-4354-87df-eaaed846e9c8,2022-01-19 12:02:16.051,events,"[""events"",""web_page""]",events,2fa2be59-2a56-47c4-9aa9-7cbc2a25dabe +61e93661-efc4-452a-a30e-86578e4ad887,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,61e93661-efc4-452a-a30e-86578e4ad887,2022-01-20 19:07:04.350,events,"[""events"",""web_page""]",events,1a5bebe2-b26a-439f-b826-02257d351292 +a059d0d5-56f9-4a39-838d-3227f8b58e5a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a059d0d5-56f9-4a39-838d-3227f8b58e5a,2022-01-19 11:17:46.106,events,"[""events"",""web_page""]",events,bb897ed9-bf72-4c56-824d-07f0707d6a71 +6e92f3c3-bb20-43ef-b4fe-39d4598fcac3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,6e92f3c3-bb20-43ef-b4fe-39d4598fcac3,2022-01-19 12:00:35.599,events,"[""events"",""web_page""]",events,c1e2db3e-67ac-43c8-968f-8d4d7e856ce7 +c7fcd7bd-0780-4e5e-9498-5e33d0de640c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c7fcd7bd-0780-4e5e-9498-5e33d0de640c,2022-01-19 11:09:46.741,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +97257f14-93dc-4c4e-bbae-6ce223aeb328,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,97257f14-93dc-4c4e-bbae-6ce223aeb328,2022-01-18 21:57:49.252,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +43fccbd3-66f1-478c-941a-d0707ff59fd1,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,43fccbd3-66f1-478c-941a-d0707ff59fd1,2022-01-18 21:57:48.470,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +95ee122f-7260-48c4-847e-75c4200cae36,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,95ee122f-7260-48c4-847e-75c4200cae36,2022-01-18 21:57:48.536,events,"[""events"",""web_page""]",events,825b6905-1c30-457e-b068-6728ca9d7425 +48a67d79-315f-42ac-83a3-f04ea0b8b290,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,48a67d79-315f-42ac-83a3-f04ea0b8b290,2022-01-19 11:09:50.696,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +4e983606-555d-4a81-b112-bcf471c928ec,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4e983606-555d-4a81-b112-bcf471c928ec,2022-01-20 16:28:54.427,events,"[""events"",""web_page""]",events,fa0b5633-9873-422a-a507-de16e58a4c91 +44ec9c35-f94d-4982-9c0f-d2ab2f330c28,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,44ec9c35-f94d-4982-9c0f-d2ab2f330c28,2022-01-19 12:00:36.021,events,"[""events"",""web_page""]",events,c1e2db3e-67ac-43c8-968f-8d4d7e856ce7 +a73dcfcf-962a-45c0-b93a-3f7e42b258eb,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a73dcfcf-962a-45c0-b93a-3f7e42b258eb,2022-01-20 16:25:54.988,events,"[""events"",""web_page""]",events,acb69ffc-3d79-4870-a543-dc7952599720 +aaf34e1d-718d-43dc-adc8-1b3c4165cacf,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,aaf34e1d-718d-43dc-adc8-1b3c4165cacf,2022-01-20 16:25:57.029,events,"[""events"",""web_page""]",events,acb69ffc-3d79-4870-a543-dc7952599720 +9e7168e6-e507-471d-a919-c6bd321bce7a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,9e7168e6-e507-471d-a919-c6bd321bce7a,2022-01-19 11:09:51.485,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +2957e918-7cf3-4792-8549-964a826012cb,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2957e918-7cf3-4792-8549-964a826012cb,2022-01-19 11:09:53.767,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +a4206470-e919-450b-ac64-2dc867900514,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a4206470-e919-450b-ac64-2dc867900514,2022-01-20 19:35:04.880,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +303bdac2-769b-486b-852a-c4f458e1e6eb,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,303bdac2-769b-486b-852a-c4f458e1e6eb,2022-01-20 21:33:55.330,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +5e0f381a-062c-4f25-af4f-a6d5d3a720e4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5e0f381a-062c-4f25-af4f-a6d5d3a720e4,2022-01-20 19:03:59.247,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +07f62104-abb5-4332-8124-8671638227d3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,07f62104-abb5-4332-8124-8671638227d3,2022-01-20 21:33:59.119,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +765420f9-6292-4219-b7f7-010f7d25a6e4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,765420f9-6292-4219-b7f7-010f7d25a6e4,2022-01-20 19:35:08.991,events,"[""events"",""web_page""]",events,1a2238b8-0abe-4b5e-9d8a-dc8fc1b2a7d6 +2bd2e42e-1c0a-41a6-a8a6-066c009c94a8,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2bd2e42e-1c0a-41a6-a8a6-066c009c94a8,2022-01-20 19:04:06.400,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +cb24b899-982c-426e-90c0-1fa3137e7fc2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,cb24b899-982c-426e-90c0-1fa3137e7fc2,2022-01-20 19:05:11.337,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +3ce7000f-1191-448d-84cb-bc742ce4e027,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3ce7000f-1191-448d-84cb-bc742ce4e027,2022-01-19 11:46:23.823,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +c74a7ba3-0a71-419a-aa46-a902c76ba09d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c74a7ba3-0a71-419a-aa46-a902c76ba09d,2022-01-18 12:07:27.099,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +f657704e-9b4f-43a2-a088-9e11c30f54a7,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,f657704e-9b4f-43a2-a088-9e11c30f54a7,2022-01-18 21:50:13.843,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +54e44960-c1fa-49e6-9c73-eef6ed72a386,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,54e44960-c1fa-49e6-9c73-eef6ed72a386,2022-01-18 21:50:13.890,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +68e56ac4-060f-4bcd-b71b-661eb1715973,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,68e56ac4-060f-4bcd-b71b-661eb1715973,2022-01-18 22:01:10.835,events,"[""events"",""web_page""]",events,83fcb20c-f3cb-4f12-a1b4-9d1c0e086163 +1209f04d-3c06-4f45-8087-b0e7c1bfd6f5,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,1209f04d-3c06-4f45-8087-b0e7c1bfd6f5,2022-01-19 12:02:53.415,events,"[""events"",""web_page""]",events,8e8967da-859e-4396-9323-2f704ee44955 +e8d916ac-4c51-4d91-a340-a0a685a4b051,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e8d916ac-4c51-4d91-a340-a0a685a4b051,2022-01-19 11:09:54.395,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +4c9b3006-43ba-4dc3-b04d-348818919e8d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4c9b3006-43ba-4dc3-b04d-348818919e8d,2022-01-19 11:09:59.938,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +22eb0b31-85f6-49c9-84ae-08e7652cb3ba,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,22eb0b31-85f6-49c9-84ae-08e7652cb3ba,2022-01-20 16:25:57.921,events,"[""events"",""web_page""]",events,acb69ffc-3d79-4870-a543-dc7952599720 +19d279fc-bbcd-411f-a8fb-b345ff8b0ffe,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,19d279fc-bbcd-411f-a8fb-b345ff8b0ffe,2022-01-19 11:10:00.307,events,"[""events"",""web_page""]",events,e02599e2-2608-4baa-8c8c-7434ce6ff44b +fba2fbe9-330f-4066-9776-183f72e6eab3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fba2fbe9-330f-4066-9776-183f72e6eab3,2022-01-19 11:39:22.917,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +86eda9ba-4578-4d41-af16-c1a21babb156,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,86eda9ba-4578-4d41-af16-c1a21babb156,2022-01-18 21:51:41.749,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +174f3b87-8e5e-4a60-980f-2986b924e750,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,174f3b87-8e5e-4a60-980f-2986b924e750,2022-01-18 21:52:12.956,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +89c05648-4b1c-4ad0-841c-f84c49b3b863,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,89c05648-4b1c-4ad0-841c-f84c49b3b863,2022-01-18 21:52:04.996,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +b987edd1-3a10-42cb-baf8-8ec261264aef,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b987edd1-3a10-42cb-baf8-8ec261264aef,2022-01-18 21:52:26.207,events,"[""events"",""web_page""]",events,42c00ee8-365a-41c7-8485-d07b8afd8db3 +083a7194-dfe1-42fa-be76-8ca98f3585f5,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,083a7194-dfe1-42fa-be76-8ca98f3585f5,2022-01-19 09:17:07.433,events,"[""events"",""web_page""]",events,16b7a187-0437-4573-8fbb-e6d9cf1ac171 +d91e6d07-ee1d-43dd-a523-8460f495a926,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d91e6d07-ee1d-43dd-a523-8460f495a926,2022-01-20 16:23:48.595,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +0b1801e2-7c57-44ff-952f-c70aef6509f3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,0b1801e2-7c57-44ff-952f-c70aef6509f3,2022-01-20 16:23:49.993,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +4af3888e-11a9-4020-bae4-b2f7960f2eaf,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,4af3888e-11a9-4020-bae4-b2f7960f2eaf,2022-01-20 16:23:51.764,events,"[""events"",""web_page""]",events,d1aa9d5c-f8fd-42a7-9d64-9c7a3e734a5a +ad444009-554c-489d-bac0-c2daf62db529,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ad444009-554c-489d-bac0-c2daf62db529,2022-01-18 22:01:27.837,events,"[""events"",""web_page""]",events,83fcb20c-f3cb-4f12-a1b4-9d1c0e086163 +76e2f1e6-2cdc-45aa-b555-9291b79f139d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,76e2f1e6-2cdc-45aa-b555-9291b79f139d,2022-01-20 19:06:02.334,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +970b7c4d-8fd9-4829-936f-a93fa4716d62,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,970b7c4d-8fd9-4829-936f-a93fa4716d62,2022-01-20 19:05:28.004,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +c983375d-09e5-4125-b3f8-ad5c16fa5cb9,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c983375d-09e5-4125-b3f8-ad5c16fa5cb9,2022-01-20 19:05:28.330,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +df67dbc0-5526-4caf-9f9c-491a4e6dab98,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,df67dbc0-5526-4caf-9f9c-491a4e6dab98,2022-01-20 19:06:03.292,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +58394af2-6dfd-438d-96d4-523ac7bed442,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,58394af2-6dfd-438d-96d4-523ac7bed442,2022-01-19 12:00:39.656,events,"[""events"",""web_page""]",events,c1e2db3e-67ac-43c8-968f-8d4d7e856ce7 +c5c6fc2e-f1b3-4eb7-83d4-08d1b196ce59,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,c5c6fc2e-f1b3-4eb7-83d4-08d1b196ce59,2022-01-20 19:06:04.285,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +180d980f-0397-4527-b3af-f29bbf187874,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,180d980f-0397-4527-b3af-f29bbf187874,2022-01-20 19:06:05.287,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +fcb2d151-da31-4b59-bfb7-4a30d20aa2d4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,fcb2d151-da31-4b59-bfb7-4a30d20aa2d4,2022-01-18 22:01:35.011,events,"[""events"",""web_page""]",events,83fcb20c-f3cb-4f12-a1b4-9d1c0e086163 +389e7819-d9c3-4325-a70b-b6658fc1f44e,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,389e7819-d9c3-4325-a70b-b6658fc1f44e,2022-01-20 17:03:42.917,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +8220f1c7-4207-41d7-a878-efccb8939284,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8220f1c7-4207-41d7-a878-efccb8939284,2022-01-20 17:03:45.327,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +d62e3683-d461-4844-b177-b240d0093e06,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d62e3683-d461-4844-b177-b240d0093e06,2022-01-20 20:44:47.347,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +8c7bf7d1-2824-428b-a7a0-a4794db01ac3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,8c7bf7d1-2824-428b-a7a0-a4794db01ac3,2022-01-20 20:44:51.710,events,"[""events"",""web_page""]",events,8b6256d5-d842-43db-8009-b9f5cf2f92c8 +2bb675df-5cc8-4f0e-abcf-0126f9366a4d,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2bb675df-5cc8-4f0e-abcf-0126f9366a4d,2022-01-20 17:03:15.041,events,"[""events"",""web_page""]",events,9da42b88-c8bf-4c5d-8d1b-985af97f2e10 +80f8e7e3-8a07-48ea-a802-69caa640f716,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,80f8e7e3-8a07-48ea-a802-69caa640f716,2022-01-20 17:03:14.877,events,"[""events"",""web_page""]",events,9da42b88-c8bf-4c5d-8d1b-985af97f2e10 +92fc228b-2590-4b69-bde1-a695691c468a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,92fc228b-2590-4b69-bde1-a695691c468a,2022-01-20 19:06:06.286,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +2ce44094-fbaf-4e09-a8cb-ec238da55aa3,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,2ce44094-fbaf-4e09-a8cb-ec238da55aa3,2022-01-20 17:03:36.104,events,"[""events"",""web_page""]",events,9da42b88-c8bf-4c5d-8d1b-985af97f2e10 +ac4a5bd1-4deb-48d8-8311-6c0d6b580b08,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ac4a5bd1-4deb-48d8-8311-6c0d6b580b08,2022-01-20 19:06:07.288,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +12ea99df-9bac-44e0-8193-5a471c677f47,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,12ea99df-9bac-44e0-8193-5a471c677f47,2022-01-20 19:06:08.312,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +47dfc9c8-2092-460b-bb9d-6a9efabd8959,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,47dfc9c8-2092-460b-bb9d-6a9efabd8959,2022-01-20 19:06:09.291,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +7eaaa450-2426-4fe3-9adf-0e026dcb2390,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7eaaa450-2426-4fe3-9adf-0e026dcb2390,2022-01-20 19:06:10.293,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +16667a78-5232-4d1b-8c73-fc22c77c941a,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,16667a78-5232-4d1b-8c73-fc22c77c941a,2022-01-20 19:06:11.289,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +d0e1def3-410d-416f-9f9b-183d22bce282,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,d0e1def3-410d-416f-9f9b-183d22bce282,2022-01-20 19:06:12.292,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +e99dc85a-368e-4f95-8043-a2448a6d4e75,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,e99dc85a-368e-4f95-8043-a2448a6d4e75,2022-01-18 21:56:36.623,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +5aa41c69-b462-41ef-be48-9dffd9c377c2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,5aa41c69-b462-41ef-be48-9dffd9c377c2,2022-01-18 21:56:36.300,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +b880e0cc-bd0a-40d7-902a-eb916e5c0b24,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,b880e0cc-bd0a-40d7-902a-eb916e5c0b24,2022-01-18 21:56:36.711,events,"[""events"",""web_page""]",events,5601236c-d0cb-4bed-86ad-7f1a3c2a3492 +1b467ee7-649d-4e9e-875a-504d9a769aa2,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,1b467ee7-649d-4e9e-875a-504d9a769aa2,2022-01-20 19:06:13.294,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +3db8bc96-4030-4f4e-aaa7-e22431e9ec77,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3db8bc96-4030-4f4e-aaa7-e22431e9ec77,2022-01-18 21:25:14.113,events,"[""events"",""web_page""]",events,87c8e627-6145-425b-ad28-7e120fa11f9f +479727be-bf7b-473e-b7f4-bb9ff0b12ca6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,479727be-bf7b-473e-b7f4-bb9ff0b12ca6,2022-01-18 21:25:14.531,events,"[""events"",""web_page""]",events,87c8e627-6145-425b-ad28-7e120fa11f9f +a944dc9a-460c-47fa-b6e5-aa5f00e8376f,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,a944dc9a-460c-47fa-b6e5-aa5f00e8376f,2022-01-18 21:25:15.040,events,"[""events"",""web_page""]",events,87c8e627-6145-425b-ad28-7e120fa11f9f +14f9d789-71d7-4e1d-be50-344b3927ccf4,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,14f9d789-71d7-4e1d-be50-344b3927ccf4,2022-01-19 11:54:15.907,events,"[""events"",""web_page""]",events,733239f7-66b2-413f-bf8e-f722293e471b +7af0eb49-7835-4723-b141-25dc084a139c,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,7af0eb49-7835-4723-b141-25dc084a139c,2022-01-18 12:15:19.102,events,"[""events"",""web_page""]",events,89438633-4f3d-482e-b9fe-d311abc61890 +ea713e85-d01d-43e2-b0f0-ef037d2a2528,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,ea713e85-d01d-43e2-b0f0-ef037d2a2528,2022-01-20 19:06:18.356,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +94581bf0-a25c-4648-aa25-0e6e2d523ad6,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,94581bf0-a25c-4648-aa25-0e6e2d523ad6,2022-01-20 19:06:40.953,events,"[""events"",""web_page""]",events,35a9f071-3431-4505-bebd-2825ee1c6ad6 +3c2ebb7f-1c65-4175-97dc-1a763feb4b18,com.snowplowanalytics.snowplow,web_page,jsonschema,1-0-0,3c2ebb7f-1c65-4175-97dc-1a763feb4b18,2022-01-20 19:17:13.016,events,"[""events"",""web_page""]",events,794f3afa-d0a9-459a-8ca6-31b2746e5db6 diff --git a/integration_tests/data/source/snowplow_youtube_context.csv b/integration_tests/data/source/com_youtube_youtube_1.csv similarity index 100% rename from integration_tests/data/source/snowplow_youtube_context.csv rename to integration_tests/data/source/com_youtube_youtube_1.csv diff --git a/integration_tests/data/source/snowplow_html5_media_element_context.csv b/integration_tests/data/source/org_whatwg_media_element_1.csv similarity index 100% rename from integration_tests/data/source/snowplow_html5_media_element_context.csv rename to integration_tests/data/source/org_whatwg_media_element_1.csv diff --git a/integration_tests/data/source/snowplow_html5_video_element_context.csv b/integration_tests/data/source/org_whatwg_video_element_1.csv similarity index 100% rename from integration_tests/data/source/snowplow_html5_video_element_context.csv rename to integration_tests/data/source/org_whatwg_video_element_1.csv diff --git a/integration_tests/dbt_project.yml b/integration_tests/dbt_project.yml index 8794f0b..9197bb6 100644 --- a/integration_tests/dbt_project.yml +++ b/integration_tests/dbt_project.yml @@ -37,35 +37,19 @@ models: +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" snowflake: +enabled: "{{ target.type == 'snowflake' | as_bool() }}" - snowplow_web: - page_views: - enabled: false - sessions: - enabled: false - user_mapping: - enabled: false - users: - enabled: false vars: - snowplow__enable_custom_example: false - snowplow_web: - snowplow__events: "{{ ref('snowplow_media_player_events_stg') }}" - snowplow__page_view_context: "{{ ref('snowplow_web_page_view_context_stg') }}" - snowplow__start_date: "2022-01-17" - snowplow__backfill_limit_days: 2 snowplow_media_player: snowplow__percent_progress_boundaries: [10, 25, 50, 75] snowplow__enable_youtube: true snowplow__enable_whatwg_media: true snowplow__enable_whatwg_video: true - snowplow__media_player_event_context: "{{ ref('snowplow__media_player_event_context_stg') }}" - snowplow__media_player_context: "{{ ref('snowplow__media_player_context_stg') }}" - snowplow__youtube_context: "{{ ref('snowplow__youtube_context_stg') }}" - snowplow__html5_media_element_context: "{{ ref('snowplow__html5_media_element_context_stg') }}" - snowplow__html5_video_element_context: "{{ ref('snowplow__html5_video_element_context_stg') }}" - + snowplow__events: "{{ ref('snowplow_media_player_events_stg') }}" + snowplow__page_view_context: "snowplow_web_page_view_context" + snowplow__start_date: "2022-01-17" + snowplow__backfill_limit_days: 30 + snowplow__atomic_schema: "{{ target.schema }}_snplw_media_player_int_tests" seeds: quote_columns: false @@ -132,21 +116,41 @@ seeds: derived_tstamp: timestamp true_tstamp: timestamp load_tstamp: timestamp - snowplow_media_player_context: + + com_snowplowanalytics_snowplow_media_player_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" +quote_columns: true +column_types: root_tstamp: timestamp - snowplow_html5_media_element_context: + + org_whatwg_media_element_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + +quote_columns: true +column_types: root_tstamp: timestamp default_playback_rate: float - snowplow_html5_video_element_context: + + org_whatwg_video_element_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + +quote_columns: true + +column_types: + root_tstamp: timestamp + + com_snowplowanalytics_snowplow_media_player_event_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + +quote_columns: true +column_types: root_tstamp: timestamp - snowplow_media_player_event_context: + + com_youtube_youtube_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + +quote_columns: true +column_types: root_tstamp: timestamp - snowplow_youtube_context: + + com_snowplowanalytics_snowplow_web_page_1: + +enabled: "{{ target.type in ['redshift', 'postgres'] | as_bool() }}" + +quote_columns: true +column_types: root_tstamp: timestamp diff --git a/integration_tests/models/source/default/snowplow__html5_media_element_context_stg.sql b/integration_tests/models/source/default/snowplow__html5_media_element_context_stg.sql deleted file mode 100644 index ff39537..0000000 --- a/integration_tests/models/source/default/snowplow__html5_media_element_context_stg.sql +++ /dev/null @@ -1,5 +0,0 @@ - -select - * - -from {{ ref('snowplow_html5_media_element_context') }} diff --git a/integration_tests/models/source/default/snowplow__html5_video_element_context_stg.sql b/integration_tests/models/source/default/snowplow__html5_video_element_context_stg.sql deleted file mode 100644 index d2f8bd7..0000000 --- a/integration_tests/models/source/default/snowplow__html5_video_element_context_stg.sql +++ /dev/null @@ -1,7 +0,0 @@ - -select - * - -from {{ ref('snowplow_html5_video_element_context') }} - - diff --git a/integration_tests/models/source/default/snowplow__media_player_context_stg.sql b/integration_tests/models/source/default/snowplow__media_player_context_stg.sql deleted file mode 100644 index cc08349..0000000 --- a/integration_tests/models/source/default/snowplow__media_player_context_stg.sql +++ /dev/null @@ -1,5 +0,0 @@ - -select - * - -from {{ ref('snowplow_media_player_context') }} diff --git a/integration_tests/models/source/default/snowplow__media_player_event_context_stg.sql b/integration_tests/models/source/default/snowplow__media_player_event_context_stg.sql deleted file mode 100644 index d3644e1..0000000 --- a/integration_tests/models/source/default/snowplow__media_player_event_context_stg.sql +++ /dev/null @@ -1,6 +0,0 @@ - -select - * - -from {{ ref('snowplow_media_player_event_context') }} - diff --git a/integration_tests/models/source/default/snowplow__youtube_context_stg.sql b/integration_tests/models/source/default/snowplow__youtube_context_stg.sql deleted file mode 100644 index f1bba7c..0000000 --- a/integration_tests/models/source/default/snowplow__youtube_context_stg.sql +++ /dev/null @@ -1,6 +0,0 @@ - -select - * - -from {{ ref('snowplow_youtube_context') }} - diff --git a/macros/allow_refresh.sql b/macros/allow_refresh.sql new file mode 100644 index 0000000..ef4f2de --- /dev/null +++ b/macros/allow_refresh.sql @@ -0,0 +1,17 @@ +{# Default: Allow refresh in dev, block refresh otherwise. dev defined by snowplow__dev_target_name #} + +{% macro allow_refresh() %} + {{ return(adapter.dispatch('allow_refresh', 'snowplow_media_player')()) }} +{% endmacro %} + +{% macro default__allow_refresh() %} + + {% set allow_refresh = snowplow_utils.get_value_by_target( + dev_value=none, + default_value=var('snowplow__allow_refresh'), + dev_target_name=var('snowplow__dev_target_name') + ) %} + + {{ return(allow_refresh) }} + +{% endmacro %} diff --git a/macros/event_name_filter.sql b/macros/event_name_filter.sql new file mode 100644 index 0000000..c6f9e01 --- /dev/null +++ b/macros/event_name_filter.sql @@ -0,0 +1,14 @@ +{# Filters on event_name if provided #} +{% macro event_name_filter(event_names) %} + + {%- if event_names|length -%} + + lower(event_name) in ('{{ event_names|map("lower")|join("','") }}') --filter on event_name if provided + + {%- else -%} + + true + + {%- endif -%} + +{% endmacro %} diff --git a/macros/snowplow_delete_from_manifest.sql b/macros/snowplow_delete_from_manifest.sql new file mode 100644 index 0000000..d818b85 --- /dev/null +++ b/macros/snowplow_delete_from_manifest.sql @@ -0,0 +1,3 @@ +{% macro snowplow_media_player_delete_from_manifest(models) %} + {{ snowplow_utils.snowplow_delete_from_manifest(models, ref('snowplow_media_player_incremental_manifest'))}} +{% endmacro %} diff --git a/models/base/manifest/base_manifest.yml b/models/base/manifest/base_manifest.yml new file mode 100644 index 0000000..4eb241a --- /dev/null +++ b/models/base/manifest/base_manifest.yml @@ -0,0 +1,45 @@ +version: 2 + +models: + - name: snowplow_media_player_base_sessions_lifecycle_manifest + description: '{{ doc("table_base_sessions_lifecycle_manifest") }}' + columns: + - name: session_id + description: '{{ doc("col_domain_sessionid") }}' + tags: + - primary-key + tests: + - unique + - not_null + - name: domain_userid + description: '{{ doc("col_domain_userid") }}' + - name: start_tstamp + description: The `collector_tstamp` when the session began + tests: + - not_null + - name: end_tstamp + description: The `collector_tstamp` when the session ended + tests: + - not_null + - name: snowplow_media_player_incremental_manifest + description: '{{ doc("table_base_incremental_manifest") }}' + columns: + - name: model + description: The name of the model. + tags: + - primary-key + tests: + - unique + - not_null + - name: last_success + description: The timestamp of the latest event consumed by the model, based on `collector_tstamp` + - name: snowplow_media_player_base_quarantined_sessions + description: '{{ doc("table_base_quarantined_sessions") }}' + columns: + - name: session_id + description: The `session_id` of the quarantined session + tags: + - primary-key + tests: + - unique + - not_null diff --git a/models/base/manifest/snowplow_media_player_base_quarantined_sessions.sql b/models/base/manifest/snowplow_media_player_base_quarantined_sessions.sql new file mode 100644 index 0000000..fd4a352 --- /dev/null +++ b/models/base/manifest/snowplow_media_player_base_quarantined_sessions.sql @@ -0,0 +1,29 @@ +{{ + config( + materialized='incremental', + full_refresh=snowplow_media_player.allow_refresh(), + sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')), + tblproperties={ + 'delta.autoOptimize.optimizeWrite' : 'true', + 'delta.autoOptimize.autoCompact' : 'true' + } + ) +}} + +/* +Boilerplate to generate table. +Table updated as part of post-hook on sessions_this_run +Any sessions exceeding max_session_days are quarantined +Once quarantined, any subsequent events from the session will not be processed. +This significantly reduces table scans +*/ + +with prep as ( + select + cast(null as {{ dbt.type_string() }}) as session_id +) + +select * + +from prep +where false diff --git a/models/base/manifest/snowplow_media_player_base_sessions_lifecycle_manifest.sql b/models/base/manifest/snowplow_media_player_base_sessions_lifecycle_manifest.sql new file mode 100644 index 0000000..b3480e9 --- /dev/null +++ b/models/base/manifest/snowplow_media_player_base_sessions_lifecycle_manifest.sql @@ -0,0 +1,96 @@ +{{ + config( + materialized="incremental", + unique_key='session_id', + upsert_date_key='start_tstamp', + sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')), + partition_by = snowplow_utils.get_value_by_target_type(bigquery_val={ + "field": "start_tstamp", + "data_type": "timestamp" + }, databricks_val='start_tstamp_date'), + full_refresh=snowplow_media_player.allow_refresh(), + tags=["manifest"], + snowplow_optimize=true + ) +}} + +-- Known edge cases: +-- 1: Rare case with multiple domain_userid per session. + +{% set lower_limit, upper_limit, _ = snowplow_utils.return_base_new_event_limits(ref('snowplow_media_player_base_new_event_limits')) %} +{% set session_lookback_limit = snowplow_utils.get_session_lookback_limit(lower_limit) %} +{% set is_run_with_new_events = snowplow_utils.is_run_with_new_events('snowplow_media_player') %} + +with new_events_session_ids as ( + select + e.domain_sessionid as session_id, + max(e.domain_userid) as domain_userid, -- Edge case 1: Arbitary selection to avoid window function like first_value. + min(e.collector_tstamp) as start_tstamp, + max(e.collector_tstamp) as end_tstamp + + from {{ var('snowplow__events') }} e + + where + e.domain_sessionid is not null + and not exists (select 1 from {{ ref('snowplow_media_player_base_quarantined_sessions') }} as a where a.session_id = e.domain_sessionid) -- don't continue processing v.long sessions + and e.dvce_sent_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__days_late_allowed", 3), 'dvce_created_tstamp') }} -- don't process data that's too late + and e.collector_tstamp >= {{ lower_limit }} + and e.collector_tstamp <= {{ upper_limit }} + and {{ snowplow_utils.app_id_filter(var("snowplow__app_id",[])) }} + and {{ event_name_filter(var("snowplow__media_event_names", ["media_player_event"]))}} + and {{ is_run_with_new_events }} --don't reprocess sessions that have already been processed. + {% if var('snowplow__derived_tstamp_partitioned', true) and target.type == 'bigquery' | as_bool() %} -- BQ only + and e.derived_tstamp >= {{ lower_limit }} + and e.derived_tstamp <= {{ upper_limit }} + {% endif %} + + group by 1 + ) + +{% if is_incremental() %} + +, previous_sessions as ( + select * + + from {{ this }} + + where start_tstamp >= {{ session_lookback_limit }} + and {{ is_run_with_new_events }} --don't reprocess sessions that have already been processed. +) + +, session_lifecycle as ( + select + ns.session_id, + coalesce(self.domain_userid, ns.domain_userid) as domain_userid, -- Edge case 1: Take previous value to keep domain_userid consistent. Not deterministic but performant + least(ns.start_tstamp, coalesce(self.start_tstamp, ns.start_tstamp)) as start_tstamp, + greatest(ns.end_tstamp, coalesce(self.end_tstamp, ns.end_tstamp)) as end_tstamp -- BQ 1 NULL will return null hence coalesce + + from new_events_session_ids ns + left join previous_sessions as self + on ns.session_id = self.session_id + + where + self.session_id is null -- process all new sessions + or self.end_tstamp < {{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'self.start_tstamp') }} --stop updating sessions exceeding 3 days + ) + +{% else %} + +, session_lifecycle as ( + + select * from new_events_session_ids + +) + +{% endif %} + +select + sl.session_id, + sl.domain_userid, + sl.start_tstamp, + least({{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'sl.start_tstamp') }}, sl.end_tstamp) as end_tstamp -- limit session length to max_session_days + {% if target.type in ['databricks', 'spark'] -%} + , DATE(sl.start_tstamp) as start_tstamp_date + {%- endif %} + +from session_lifecycle sl diff --git a/models/base/manifest/snowplow_media_player_incremental_manifest.sql b/models/base/manifest/snowplow_media_player_incremental_manifest.sql new file mode 100644 index 0000000..5a0ebce --- /dev/null +++ b/models/base/manifest/snowplow_media_player_incremental_manifest.sql @@ -0,0 +1,21 @@ +{{ + config( + materialized='incremental', + sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')), + full_refresh=snowplow_media_player.allow_refresh() + ) +}} + +-- Boilerplate to generate table. +-- Table updated as part of end-run hook + +with prep as ( + select + cast(null as {{ snowplow_utils.type_max_string() }}) as model, + cast('1970-01-01' as {{ type_timestamp() }}) as last_success +) + +select * + +from prep +where false diff --git a/models/web/scratch/snowplow_media_player_scratch.yml b/models/base/scratch/base_scratch.yml similarity index 58% rename from models/web/scratch/snowplow_media_player_scratch.yml rename to models/base/scratch/base_scratch.yml index eff82d4..83c501f 100644 --- a/models/web/scratch/snowplow_media_player_scratch.yml +++ b/models/base/scratch/base_scratch.yml @@ -1,8 +1,33 @@ version: 2 models: - - name: snowplow_media_player_interactions_this_run - description: '{{ doc("table_interactions_this_run") }}' + - name: snowplow_media_player_base_new_event_limits + description: '{{ doc("table_base_new_event_limits") }}' + columns: + - name: lower_limit + description: The lower `collector_tstamp` limit for the run + - name: upper_limit + description: The upper `collector_tstamp` limit for the run + + - name: snowplow_media_player_base_sessions_this_run + description: '{{ doc("table_base_sessions_this_run") }}' + columns: + - name: session_id + description: '{{ doc("col_domain_sessionid") }}' + tags: + - primary-key + tests: + - unique + - not_null + - name: domain_userid + description: '{{ doc("col_domain_userid") }}' + - name: start_tstamp + description: The `collector_tstamp` when the session began + - name: end_tstamp + description: The `collector_tstamp` when the session ended + + - name: snowplow_media_player_base_events_this_run + description: '{{ doc("table_base_events_this_run") }}' columns: - name: event_id description: '{{ doc("col_event_id") }}' @@ -72,70 +97,7 @@ models: description: '{{ doc("col_loop") }}' - name: volume description: '{{ doc("col_volume") }}' - - name: snowplow_media_player_base_this_run - description: '{{ doc("table_base_this_run") }}' - columns: - - name: play_id - description: '{{ doc("col_play_id") }}' - tags: - - primary-key - tests: - - unique - - not_null - - name: page_view_id - description: '{{ doc("col_page_view_id") }}' - - name: media_id - description: '{{ doc("col_media_id") }}' - - name: media_label - description: '{{ doc("col_media_label") }}' - - name: domain_sessionid - description: '{{ doc("col_domain_sessionid") }}' - - name: domain_userid - description: '{{ doc("col_domain_userid") }}' - - name: duration - description: '{{ doc("col_duration") }}' - - name: media_type - description: '{{ doc("col_media_type") }}' - - name: media_player_type - description: '{{ doc("col_media_player_type") }}' - - name: page_referrer - description: '{{ doc("col_page_referrer") }}' - - name: page_url - description: '{{ doc("col_page_url") }}' - - name: source_url - description: '{{ doc("col_source_url") }}' - - name: geo_region_name - description: '{{ doc("col_geo_region_name") }}' - - name: br_name - description: '{{ doc("col_br_name") }}' - - name: dvce_type - description: '{{ doc("col_dvce_type") }}' - - name: os_name - description: '{{ doc("col_os_name") }}' - - name: os_timezone - description: '{{ doc("col_os_timezone") }}' - - name: start_tstamp - description: '{{ doc("col_start_tstamp") }}' - - name: end_tstamp - description: '{{ doc("col_end_tstamp") }}' - - name: play_time_sec - description: '{{ doc("col_play_time_sec") }}' - - name: play_time_sec_muted - description: '{{ doc("col_play_time_sec_muted") }}' - - name: is_played - description: '{{ doc("col_is_played") }}' - - name: is_valid_play - description: '{{ doc("col_is_valid_play") }}' - - name: is_complete_play - description: '{{ doc("col_is_complete_play") }}' - - name: avg_playback_rate - description: '{{ doc("col_avg_playback_rate") }}' - - name: retention_rate - description: '{{ doc("col_retention_rate") }}' - - name: seeks - description: '{{ doc("col_seeks") }}' - - name: percent_progress_reached - description: '{{ doc("col_percent_progress_reached") }}' + - name: snowplow_media_player_pivot_base description: '{{ doc("table_pivot_base") }}' columns: diff --git a/models/base/scratch/bigquery/snowplow_media_player_base_events_this_run.sql b/models/base/scratch/bigquery/snowplow_media_player_base_events_this_run.sql new file mode 100644 index 0000000..86f2537 --- /dev/null +++ b/models/base/scratch/bigquery/snowplow_media_player_base_events_this_run.sql @@ -0,0 +1,305 @@ +{{ + config( + tags=["this_run"] + ) +}} + +{%- set lower_limit, upper_limit = snowplow_utils.return_limits_from_model(ref('snowplow_media_player_base_sessions_this_run'), + 'start_tstamp', + 'end_tstamp') %} + +-- handling relations for integration tests +{% if target.schema.startswith('gh_sp_media_player_dbt_') or 'dbt_matus' in target.schema %} + {%- set relation = ref('snowplow_media_player_events_stg') %} +{% else %} + {%- set relation = source('atomic', 'events') %} +{% endif %} + +with prep as ( + + select + *, + dense_rank() over (partition by ev.domain_sessionid order by ev.start_tstamp) AS event_in_session_index, + + from ( + -- without downstream joins, it's safe to dedupe by picking the first event_id found. + select + array_agg(e order by e.collector_tstamp limit 1)[offset(0)].* + + from ( + + select + + a.event_id, + a.contexts_com_snowplowanalytics_snowplow_web_page_1_0_0[safe_offset(0)].id as page_view_id, + a.domain_sessionid, + a.domain_userid, + a.page_referrer, + a.page_url, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'label', 'dtype': 'string'}], + col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as media_label, + round(cast({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'duration', 'dtype': 'int'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as float64)) as duration, + a.geo_region_name, + a.br_name, + a.dvce_type, + a.os_name, + a.os_timezone, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'type', 'dtype': 'string'}], + col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as event_type, + a.derived_tstamp as start_tstamp, + a.collector_tstamp, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'current_time', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as player_current_time, + coalesce(cast({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'playback_rate', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as float64), 1) as playback_rate, + case when {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'type', 'dtype': 'string'}], + col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} = 'ended' + then 100 + else safe_cast({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'percent_progress', 'dtype': 'int'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as int64) end as percent_progress, + cast({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'muted', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as boolean) as is_muted, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'is_live', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as is_live, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'loop', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as loop, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'volume', 'dtype': 'string'}], + col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as volume, + {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} + {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both need to be enabled for modelling html5 video tracking data.") }} + + {% elif var("snowplow__enable_youtube") %} + {% if var("snowplow__enable_whatwg_media") %} + coalesce({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'player_id', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'html_id', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}}) as media_id, + case when {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'player_id', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} is not null + then 'com.youtube-youtube' + when {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'html_id', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}} is not null + then 'org.whatwg-media_element' + else 'unknown' end as media_player_type, + coalesce({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'url', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'current_src', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}}) as source_url, + case when {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'media_type', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}} = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + coalesce({{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'playback_quality', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'video_width', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_video_element_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}||'x'||{{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'video_height', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_video_element_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}) as playback_quality + {% else %} + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'playback_quality', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a')}}, + {% endif %} + {% else %} + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'player_id', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as media_id, + 'com.youtube-youtube' as media_player_type, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'url', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as source_url, + 'video' as media_type, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'playback_quality', 'dtype': 'string'}], + col_prefix='contexts_com_youtube_youtube_1', + relation=relation, + relation_alias='a')}} + {% endif %} + + {% elif var("snowplow__enable_whatwg_media") %} + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'html_id', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as media_id, + 'org.whatwg-media_element' as media_player_type, + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'current_src', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as source_url, + case when {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'media_type', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_media_element_1_', + relation=relation, + relation_alias='a', + include_field_alias=false)}} = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + {{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'video_width', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_video_element_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}}||'x'||{{ snowplow_utils.get_optional_fields( + enabled= true, + fields=[{'field': 'video_height', 'dtype': 'string'}], + col_prefix='contexts_org_whatwg_video_element_1', + relation=relation, + relation_alias='a', + include_field_alias=false)}} as playback_quality + {% else %} + 'N/A' as playback_quality + {% endif %} + + {% else %} + {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} + {% endif %} + + from {{ var('snowplow__events') }} as a + inner join {{ ref('snowplow_media_player_base_sessions_this_run') }} as b + on a.domain_sessionid = b.session_id + + where a.collector_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'b.start_tstamp') }} + and a.dvce_sent_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__days_late_allowed", 3), 'a.dvce_created_tstamp') }} + and a.collector_tstamp >= {{ lower_limit }} + and a.collector_tstamp <= {{ upper_limit }} + {% if var('snowplow__derived_tstamp_partitioned', true) and target.type == 'bigquery' | as_bool() %} + and a.derived_tstamp >= {{ snowplow_utils.timestamp_add('hour', -1, lower_limit) }} + and a.derived_tstamp <= {{ upper_limit }} + {% endif %} + and {{ snowplow_utils.app_id_filter(var("snowplow__app_id",[])) }} + and {{ snowplow_media_player.event_name_filter(var("snowplow__media_event_names", "['media_player_event']")) }} + ) e + group by e.event_id + ) ev +) + +select + {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, + p.*, + coalesce(cast(piv.weight_rate * p.duration / 100 as {{ type_int() }}), 0) as play_time_sec, + coalesce(cast(case when p.is_muted = true then piv.weight_rate * p.duration / 100 else 0 end as {{ type_int() }}), 0) as play_time_sec_muted + + from prep p + + left join {{ ref("snowplow_media_player_pivot_base") }} piv + on p.percent_progress = piv.percent_progress diff --git a/models/base/scratch/databricks/snowplow_media_player_base_events_this_run.sql b/models/base/scratch/databricks/snowplow_media_player_base_events_this_run.sql new file mode 100644 index 0000000..6143dbc --- /dev/null +++ b/models/base/scratch/databricks/snowplow_media_player_base_events_this_run.sql @@ -0,0 +1,97 @@ +{{ + config( + tags=["this_run"] + ) +}} + +{%- set lower_limit, upper_limit = snowplow_utils.return_limits_from_model(ref('snowplow_media_player_base_sessions_this_run'), + 'start_tstamp', + 'end_tstamp') %} + +with prep AS ( + + select + + a.event_id, + a.contexts_com_snowplowanalytics_snowplow_web_page_1[0].id::string as page_view_id, + a.domain_sessionid, + b.domain_userid, + a.page_referrer, + a.page_url, + a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.label::STRING as media_label, + round(contexts_com_snowplowanalytics_snowplow_media_player_1[0].duration::float) as duration, + a.geo_region_name, + a.br_name, + a.dvce_type, + a.os_name, + a.os_timezone, + a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.type::STRING as event_type, + a.derived_tstamp as start_tstamp, + contexts_com_snowplowanalytics_snowplow_media_player_1[0].current_time::float as player_current_time, + coalesce(contexts_com_snowplowanalytics_snowplow_media_player_1[0].playback_rate::STRING, 1) as playback_rate, + case when a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.type::STRING = 'ended' then 100 else contexts_com_snowplowanalytics_snowplow_media_player_1[0].percent_progress::int end percent_progress, + contexts_com_snowplowanalytics_snowplow_media_player_1[0].muted::STRING as is_muted, + contexts_com_snowplowanalytics_snowplow_media_player_1[0].is_live::STRING as is_live, + contexts_com_snowplowanalytics_snowplow_media_player_1[0].loop::STRING as loop, + contexts_com_snowplowanalytics_snowplow_media_player_1[0].volume::STRING as volume, + {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} + {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both need to be enabled for modelling html5 video tracking data.") }} + {% elif var("snowplow__enable_youtube") %} + {% if var("snowplow__enable_whatwg_media") %} + coalesce(a.contexts_com_youtube_youtube_1[0].player_id::STRING, a.contexts_org_whatwg_media_element_1[0].html_id::STRING) as media_id, + case when a.contexts_com_youtube_youtube_1[0].player_id is not null then 'com.youtube-youtube' + when a.contexts_org_whatwg_media_element_1[0].html_id::STRING is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, + coalesce(a.contexts_com_youtube_youtube_1[0].url::STRING, a.contexts_org_whatwg_media_element_1[0].current_src::STRING) as source_url, + case when a.contexts_org_whatwg_media_element_1[0].media_type::STRING = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + coalesce(a.contexts_com_youtube_youtube_1[0].playback_quality::STRING, a.contexts_org_whatwg_video_element_1[0].video_width::STRING||'x'||a.contexts_org_whatwg_video_element_1[0].video_height::STRING) as playback_quality + {% else %} + a.contexts_com_youtube_youtube_1[0].playback_quality::STRING + {% endif %} + {% else %} + a.contexts_com_youtube_youtube_1[0].player_id::STRING as media_id, + 'com.youtube-youtube' as media_player_type, + a.contexts_com_youtube_youtube_1[0].url::STRING as source_url, + 'video' as media_type, + a.contexts_com_youtube_youtube_1[0].playback_quality::STRING + {% endif %} + {% elif var("snowplow__enable_whatwg_media") %} + a.contexts_org_whatwg_media_element_1[0].html_id::STRING as media_id, + 'org.whatwg-media_element' as media_player_type, + a.contexts_org_whatwg_media_element_1[0].current_src::STRING as source_url, + case when a.contexts_org_whatwg_media_element_1[0].media_type::STRING = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + a.contexts_org_whatwg_video_element_1[0].video_width::STRING||'x'||a.contexts_org_whatwg_video_element_1[0].video_height::STRING as playback_quality + {% else %} + 'N/A' as playback_quality + {% endif %} + {% else %} + {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} + {% endif %} + + from {{ var('snowplow__events') }} as a + inner join {{ ref('snowplow_media_player_base_sessions_this_run') }} as b + on a.domain_sessionid = b.session_id + + where a.collector_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'b.start_tstamp') }} + and a.dvce_sent_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__days_late_allowed", 3), 'a.dvce_created_tstamp') }} + and a.collector_tstamp >= {{ lower_limit }} + and a.collector_tstamp <= {{ upper_limit }} + and {{ snowplow_utils.app_id_filter(var("snowplow__app_id",[])) }} + and {{ snowplow_media_player.event_name_filter(var("snowplow__media_event_names", "['media_player_event']")) }} + + qualify row_number() over (partition by a.event_id order by a.collector_tstamp) = 1 +) + +select + {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, + p.*, + coalesce(cast(round(piv.weight_rate * p.duration / 100) as {{ type_int() }}), 0) as play_time_sec, + coalesce(cast(case when p.is_muted = true then round(piv.weight_rate * p.duration / 100) else 0 end as {{ type_int() }}), 0) as play_time_sec_muted, + + dense_rank() over (partition by domain_sessionid order by start_tstamp) AS event_in_session_index + + from prep p + + left join {{ ref("snowplow_media_player_pivot_base") }} piv + on p.percent_progress = piv.percent_progress diff --git a/models/base/scratch/default/snowplow_media_player_base_events_this_run.sql b/models/base/scratch/default/snowplow_media_player_base_events_this_run.sql new file mode 100644 index 0000000..cc4f1b0 --- /dev/null +++ b/models/base/scratch/default/snowplow_media_player_base_events_this_run.sql @@ -0,0 +1,374 @@ +{{ + config( + sort='collector_tstamp', + dist='event_id', + tags=["this_run"] + ) +}} + +{%- set lower_limit, upper_limit = snowplow_utils.return_limits_from_model(ref('snowplow_media_player_base_sessions_this_run'), + 'start_tstamp', + 'end_tstamp') %} + +/* Dedupe logic: Per dupe event_id keep earliest row ordered by collector_tstamp. + If multiple earliest rows, take arbitrary one using row_number(). */ + +with events_this_run AS ( + select + a.app_id, + a.platform, + a.etl_tstamp, + a.collector_tstamp, + a.dvce_created_tstamp, + a.event, + a.event_id, + a.txn_id, + a.name_tracker, + a.v_tracker, + a.v_collector, + a.v_etl, + a.user_id, + a.user_ipaddress, + a.user_fingerprint, + b.domain_userid, -- take domain_userid from manifest. This ensures only 1 domain_userid per session. + a.domain_sessionidx, + a.network_userid, + a.geo_country, + a.geo_region, + a.geo_city, + a.geo_zipcode, + a.geo_latitude, + a.geo_longitude, + a.geo_region_name, + a.ip_isp, + a.ip_organization, + a.ip_domain, + a.ip_netspeed, + a.page_url, + a.page_title, + a.page_referrer, + a.page_urlscheme, + a.page_urlhost, + a.page_urlport, + a.page_urlpath, + a.page_urlquery, + a.page_urlfragment, + a.refr_urlscheme, + a.refr_urlhost, + a.refr_urlport, + a.refr_urlpath, + a.refr_urlquery, + a.refr_urlfragment, + a.refr_medium, + a.refr_source, + a.refr_term, + a.mkt_medium, + a.mkt_source, + a.mkt_term, + a.mkt_content, + a.mkt_campaign, + a.se_category, + a.se_action, + a.se_label, + a.se_property, + a.se_value, + a.tr_orderid, + a.tr_affiliation, + a.tr_total, + a.tr_tax, + a.tr_shipping, + a.tr_city, + a.tr_state, + a.tr_country, + a.ti_orderid, + a.ti_sku, + a.ti_name, + a.ti_category, + a.ti_price, + a.ti_quantity, + a.pp_xoffset_min, + a.pp_xoffset_max, + a.pp_yoffset_min, + a.pp_yoffset_max, + a.useragent, + a.br_name, + a.br_family, + a.br_version, + a.br_type, + a.br_renderengine, + a.br_lang, + a.br_features_pdf, + a.br_features_flash, + a.br_features_java, + a.br_features_director, + a.br_features_quicktime, + a.br_features_realplayer, + a.br_features_windowsmedia, + a.br_features_gears, + a.br_features_silverlight, + a.br_cookies, + a.br_colordepth, + a.br_viewwidth, + a.br_viewheight, + a.os_name, + a.os_family, + a.os_manufacturer, + a.os_timezone, + a.dvce_type, + a.dvce_ismobile, + a.dvce_screenwidth, + a.dvce_screenheight, + a.doc_charset, + a.doc_width, + a.doc_height, + a.tr_currency, + a.tr_total_base, + a.tr_tax_base, + a.tr_shipping_base, + a.ti_currency, + a.ti_price_base, + a.base_currency, + a.geo_timezone, + a.mkt_clickid, + a.mkt_network, + a.etl_tags, + a.dvce_sent_tstamp, + a.refr_domain_userid, + a.refr_dvce_tstamp, + a.domain_sessionid, + a.derived_tstamp, + a.event_vendor, + a.event_name, + a.event_format, + a.event_version, + a.event_fingerprint, + a.true_tstamp, + {% if var('snowplow__enable_load_tstamp', true) %} + a.load_tstamp, + {% endif %} + row_number() over (partition by a.event_id order by a.collector_tstamp) as event_id_dedupe_index, + count(*) over (partition by a.event_id) as event_id_dedupe_count + + from {{ var('snowplow__events') }} as a + inner join {{ ref('snowplow_media_player_base_sessions_this_run') }} as b + on a.domain_sessionid = b.session_id + + where a.collector_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'b.start_tstamp') }} + and a.dvce_sent_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__days_late_allowed", 3), 'a.dvce_created_tstamp') }} + and a.collector_tstamp >= {{ lower_limit }} + and a.collector_tstamp <= {{ upper_limit }} + and {{ snowplow_utils.app_id_filter(var("snowplow__app_id",[])) }} + and {{ snowplow_media_player.event_name_filter(var("snowplow__media_event_names", "['media_player_event']")) }} + +), + +-- unpacking the media player event +{{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__media_player_event_context'), lower_limit, upper_limit) }}, +-- unpacking the media player context entity +{{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__media_player_context'), lower_limit, upper_limit) }}, +-- unpacking the youtube context entity +{%- if var("snowplow__enable_youtube") -%} + {{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__youtube_context'), lower_limit, upper_limit) }}, +{%- endif %} +-- unpacking the whatwg media context entity +{% if var("snowplow__enable_whatwg_media") -%} + {{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__html5_media_element_context'), lower_limit, upper_limit) }}, +{%- endif %} +-- unpacking the whatwg video context entity +{% if var("snowplow__enable_whatwg_video") -%} + {{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__html5_video_element_context'), lower_limit, upper_limit) }}, +{%- endif %} +-- unpacking the web page context entity +{{ snowplow_utils.get_sde_or_context(var('snowplow__atomic_schema', 'atomic'), var('snowplow__context_web_page'), lower_limit, upper_limit) }}, + + + +prep as ( +select + ev.event_id, + pv.id as page_view_id, + ev.domain_sessionid, + ev.domain_userid, + ev.page_referrer, + ev.page_url, + mpe.label as media_label, + round(mp.duration) as duration, + ev.geo_region_name, + ev.br_name, + ev.dvce_type, + ev.os_name, + ev.os_timezone, + mpe.type as event_type, + ev.derived_tstamp as start_tstamp, + mp.current_time as player_current_time, + coalesce(mp.playback_rate, 1) as playback_rate, + case when mpe.type = 'ended' then 100 else mp.percent_progress end percent_progress, + mp.muted as is_muted, + mp.is_live, + mp.loop, + mp.volume, + {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} + {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both needs to be enabled for modelling html5 video tracking data.") }} + {% elif var("snowplow__enable_youtube") %} + {% if var("snowplow__enable_whatwg_media") %} + coalesce(yt.player_id, me.html_id) as media_id, + case when yt.player_id is not null then 'com.youtube-youtube' when me.html_id is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, + coalesce(yt.url, me.current_src) as source_url, + case when me.media_type = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + coalesce(yt.playback_quality, ve.video_width||'x'||ve.video_height) as playback_quality + {% else %} + yt.playback_quality + {% endif %} + {% else %} + yt.player_id as media_id, + 'com.youtube-youtube' as media_player_type, + yt.url as source_url, + 'video' as media_type, + yt.playback_quality + {% endif %} + {% elif var("snowplow__enable_whatwg_media") %} + me.html_id as media_id, + 'org.whatwg-media_element' as media_player_type, + me.current_src as source_url, + case when me.media_type = 'audio' then 'audio' else 'video' end as media_type, + {% if var("snowplow__enable_whatwg_video") %} + ve.video_width||'x'||ve.video_height as playback_quality + {% else %} + 'N/A' as playback_quality + {% endif %} + {% else %} + {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} + {% endif %}, + + {# pv.page_view_id, + + {% if var('snowplow__disable_ecommerce_user_context', false) -%} + cast(NULL as {{ type_string() }}) as ecommerce_user_id, + cast(NULL as {{ type_string() }}) as ecommerce_user_email, + cast(NULL as {{ type_boolean() }}) as ecommerce_user_is_guest, + {%- else -%} + usr.ecommerce_user_id, + usr.ecommerce_user_email, + usr.ecommerce_user_is_guest, + {%- endif %} + + -- unpacking the ecommerce checkout step object + {% if var('snowplow__disable_ecommerce_checkouts', false) -%} + cast(NULL as {{ type_int() }}) as checkout_step_number, + cast(NULL as {{ type_string() }}) as checkout_account_type, + cast(NULL as {{ type_string() }}) as checkout_billing_full_address, + cast(NULL as {{ type_string() }}) as checkout_billing_postcode, + cast(NULL as {{ type_string() }}) as checkout_coupon_code, + cast(NULL as {{ type_string() }}) as checkout_delivery_method, + cast(NULL as {{ type_string() }}) as checkout_delivery_provider, + cast(NULL as {{ type_boolean() }}) as checkout_marketing_opt_in, + cast(NULL as {{ type_string() }}) as checkout_payment_method, + cast(NULL as {{ type_string() }}) as checkout_proof_of_payment, + cast(NULL as {{ type_string() }}) as checkout_shipping_full_address, + cast(NULL as {{ type_string() }}) as checkout_shipping_postcode, + {%- else -%} + checkout.checkout_step as checkout_step_number, + checkout.checkout_account_type, + checkout.checkout_billing_full_address, + checkout.checkout_billing_postcode, + checkout.checkout_coupon_code, + checkout.checkout_delivery_method, + checkout.checkout_delivery_provider, + checkout.checkout_marketing_opt_in, + checkout.checkout_payment_method, + checkout.checkout_proof_of_payment, + checkout.checkout_shipping_full_address, + checkout.checkout_shipping_postcode, + {%- endif %} + + -- unpacking the ecommerce page object + {% if var('snowplow__disable_ecommerce_page_context', false) -%} + CAST(NULL as {{ type_string() }}) as ecommerce_page_type, + CAST(NULL as {{ type_string() }}) as ecommerce_page_language, + CAST(NULL as {{ type_string() }}) as ecommerce_page_locale, + {%- else -%} + ecom_page.ecommerce_page_type, + ecom_page.ecommerce_page_language, + ecom_page.ecommerce_page_locale, + {%- endif %} + + -- unpacking the ecommerce transaction object + {% if var('snowplow__disable_ecommerce_transactions', false) -%} + CAST(NULL AS {{ type_string() }}) as transaction_id, + CAST(NULL AS {{ type_string() }}) as transaction_currency, + CAST(NULL AS {{ type_string() }}) as transaction_payment_method, + CAST(NULL AS decimal(9,2)) as transaction_revenue, + CAST(NULL AS {{ type_int() }}) as transaction_total_quantity, + CAST(NULL AS {{ type_boolean() }}) as transaction_credit_order, + CAST(NULL AS decimal(9,2)) as transaction_discount_amount, + CAST(NULL AS {{ type_string() }}) as transaction_discount_code, + CAST(NULL AS decimal(9,2)) as transaction_shipping, + CAST(NULL AS decimal(9,2)) as transaction_tax, + {%- else -%} + trans.transaction_transaction_id as transaction_id, + trans.transaction_currency, + trans.transaction_payment_method, + trans.transaction_revenue, + trans.transaction_total_quantity, + trans.transaction_credit_order, + trans.transaction_discount_amount, + trans.transaction_discount_code, + trans.transaction_shipping, + trans.transaction_tax, + {%- endif %} + + -- unpacking the ecommerce cart object + {% if var('snowplow__disable_ecommerce_carts', false) -%} + CAST(NULL AS {{ type_string() }}) as cart_id, + CAST(NULL AS {{ type_string() }}) as cart_currency, + CAST(NULL AS decimal(9,2)) as cart_total_value, + {%- else -%} + carts.cart_cart_id as cart_id, + carts.cart_currency, + carts.cart_total_value, + {%- endif%} + + -- unpacking the ecommerce action object + action.ecommerce_action_type, + action.ecommerce_action_name, #} + + dense_rank() over (partition by domain_sessionid order by derived_tstamp) AS event_in_session_index + +from events_this_run ev + + +-- youtube context entity +{% if var("snowplow__enable_youtube") %} + left join {{ var('snowplow__youtube_context') }} yt on ev.event_id = yt.youtube__id and ev.collector_tstamp = yt.youtube__tstamp +{%- endif %} +-- whatwg media context entity +{% if var("snowplow__enable_whatwg_media") %} + left join {{ var('snowplow__html5_media_element_context') }} me on ev.event_id = me.media_element__id and ev.collector_tstamp = me.media_element__tstamp +{%- endif %} +-- whatwg video context entity +{% if var("snowplow__enable_whatwg_video") %} + left join {{ var('snowplow__html5_video_element_context') }} ve on ev.event_id = ve.video_element__id and ev.collector_tstamp = ve.video_element__tstamp +{%- endif %} +-- media player event + left join {{ var('snowplow__media_player_event_context') }} mpe on ev.event_id = mpe.media_player_event__id and ev.collector_tstamp = mpe.media_player_event__tstamp +-- media player context entity + left join {{ var('snowplow__media_player_context') }} mp on ev.event_id = mp.media_player__id and ev.collector_tstamp = mp.media_player__tstamp +-- web page context entity + left join {{ var('snowplow__context_web_page') }} pv on ev.event_id = pv.web_page__id and ev.collector_tstamp = pv.web_page__tstamp + + +where + ev.event_id_dedupe_index = ev.event_id_dedupe_count +) + + select + {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, + p.*, + coalesce(cast(round(piv.weight_rate * p.duration / 100) as {{ type_int() }}), 0) as play_time_sec, + coalesce(cast(case when p.is_muted then round(piv.weight_rate * p.duration / 100) end as {{ type_int() }}), 0) as play_time_sec_muted + + from prep p + + left join {{ ref("snowplow_media_player_pivot_base") }} piv + on p.percent_progress = piv.percent_progress diff --git a/models/web/scratch/interactions_this_run/redshift_postgres/sources.yml b/models/base/scratch/default/sources.yml similarity index 100% rename from models/web/scratch/interactions_this_run/redshift_postgres/sources.yml rename to models/base/scratch/default/sources.yml diff --git a/models/web/scratch/interactions_this_run/snowflake/snowplow_media_player_interactions_this_run.sql b/models/base/scratch/snowflake/snowplow_media_player_base_events_this_run.sql similarity index 50% rename from models/web/scratch/interactions_this_run/snowflake/snowplow_media_player_interactions_this_run.sql rename to models/base/scratch/snowflake/snowplow_media_player_base_events_this_run.sql index 64ec593..26974d5 100644 --- a/models/web/scratch/interactions_this_run/snowflake/snowplow_media_player_interactions_this_run.sql +++ b/models/base/scratch/snowflake/snowplow_media_player_base_events_this_run.sql @@ -1,32 +1,35 @@ {{ config( - materialized='table', tags=["this_run"], sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')) ) }} +{%- set lower_limit, upper_limit = snowplow_utils.return_limits_from_model(ref('snowplow_media_player_base_sessions_this_run'), + 'start_tstamp', + 'end_tstamp') %} with prep as ( - select - e.event_id, - e.page_view_id, - e.domain_sessionid, - e.domain_userid, - e.page_referrer, - e.page_url, - e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:label::varchar as media_label, + select + + a.event_id, + a.contexts_com_snowplowanalytics_snowplow_web_page_1[0]:id::varchar as page_view_id, + a.domain_sessionid, + b.domain_userid, + a.page_referrer, + a.page_url, + a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:label::varchar as media_label, round(contexts_com_snowplowanalytics_snowplow_media_player_1[0]:duration::int) as duration, - e.geo_region_name, - e.br_name, - e.dvce_type, - e.os_name, - e.os_timezone, - e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:type::varchar as event_type, - e.derived_tstamp as start_tstamp, + a.geo_region_name, + a.br_name, + a.dvce_type, + a.os_name, + a.os_timezone, + a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:type::varchar as event_type, + a.derived_tstamp as start_tstamp, contexts_com_snowplowanalytics_snowplow_media_player_1[0]:currentTime::float as player_current_time, coalesce(contexts_com_snowplowanalytics_snowplow_media_player_1[0]:playbackRate::varchar, 1) as playback_rate, - cast(case when e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:type::varchar = 'ended' then '100' + cast(case when a.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1:type::varchar = 'ended' then '100' when contexts_com_snowplowanalytics_snowplow_media_player_1[0]:percentProgress::varchar = '' THEN NULL else contexts_com_snowplowanalytics_snowplow_media_player_1[0]:percentProgress::varchar END AS int) percent_progress, contexts_com_snowplowanalytics_snowplow_media_player_1[0]:muted::boolean as is_muted, @@ -37,30 +40,30 @@ with prep as ( {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both need to be enabled for modelling html5 video tracking data.") }} {% elif var("snowplow__enable_youtube") %} {% if var("snowplow__enable_whatwg_media") %} - coalesce(e.contexts_com_youtube_youtube_1[0]:playerId::varchar, e.contexts_org_whatwg_media_element_1[0]:htmlId::varchar) as media_id, - case when e.contexts_com_youtube_youtube_1[0]:playerId is not null then 'com.youtube-youtube' - when e.contexts_org_whatwg_media_element_1[0]:htmlId::varchar is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, - coalesce(e.contexts_com_youtube_youtube_1[0]:url::varchar, e.contexts_org_whatwg_media_element_1[0]:currentSrc::varchar) as source_url, - case when e.contexts_org_whatwg_media_element_1[0]:mediaType::varchar = 'audio' then 'audio' else 'video' end as media_type, + coalesce(a.contexts_com_youtube_youtube_1[0]:playerId::varchar, a.contexts_org_whatwg_media_element_1[0]:htmlId::varchar) as media_id, + case when a.contexts_com_youtube_youtube_1[0]:playerId is not null then 'com.youtube-youtube' + when a.contexts_org_whatwg_media_element_1[0]:htmlId::varchar is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, + coalesce(a.contexts_com_youtube_youtube_1[0]:url::varchar, a.contexts_org_whatwg_media_element_1[0]:currentSrc::varchar) as source_url, + case when a.contexts_org_whatwg_media_element_1[0]:mediaType::varchar = 'audio' then 'audio' else 'video' end as media_type, {% if var("snowplow__enable_whatwg_video") %} - coalesce(e.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar, e.contexts_org_whatwg_video_element_1[0]:videoWidth::varchar||'x'||e.contexts_org_whatwg_video_element_1[0]:videoHeight::varchar) as playback_quality + coalesce(a.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar, a.contexts_org_whatwg_video_element_1[0]:videoWidth::varchar||'x'||a.contexts_org_whatwg_video_element_1[0]:videoHeight::varchar) as playback_quality {% else %} - e.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar + a.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar {% endif %} {% else %} - e.contexts_com_youtube_youtube_1[0]:playerId::varchar as media_id, + a.contexts_com_youtube_youtube_1[0]:playerId::varchar as media_id, 'com.youtube-youtube' as media_player_type, - e.contexts_com_youtube_youtube_1[0]:url::varchar as source_url, + a.contexts_com_youtube_youtube_1[0]:url::varchar as source_url, 'video' as media_type, - e.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar + a.contexts_com_youtube_youtube_1[0]:playbackQuality::varchar {% endif %} {% elif var("snowplow__enable_whatwg_media") %} - e.contexts_org_whatwg_media_element_1[0]:htmlId::varchar as media_id, + a.contexts_org_whatwg_media_element_1[0]:htmlId::varchar as media_id, 'org.whatwg-media_element' as media_player_type, - e.contexts_org_whatwg_media_element_1[0]:currentSrc::varchar as source_url, - case when e.contexts_org_whatwg_media_element_1[0]:mediaType::varchar = 'audio' then 'audio' else 'video' end as media_type, + a.contexts_org_whatwg_media_element_1[0]:currentSrc::varchar as source_url, + case when a.contexts_org_whatwg_media_element_1[0]:mediaType::varchar = 'audio' then 'audio' else 'video' end as media_type, {% if var("snowplow__enable_whatwg_video") %} - e.contexts_org_whatwg_video_element_1[0]:videoWidth::varchar||'x'||e.contexts_org_whatwg_video_element_1[0]:videoHeight::varchar as playback_quality + a.contexts_org_whatwg_video_element_1[0]:videoWidth::varchar||'x'||a.contexts_org_whatwg_video_element_1[0]:videoHeight::varchar as playback_quality {% else %} 'N/A' as playback_quality {% endif %} @@ -68,16 +71,30 @@ with prep as ( {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} {% endif %} - from {{ ref("snowplow_web_base_events_this_run") }} as e + from {{ var('snowplow__events') }} as a + inner join {{ ref('snowplow_media_player_base_sessions_this_run') }} as b + on a.domain_sessionid = b.session_id + + where a.collector_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__max_session_days", 3), 'b.start_tstamp') }} + and a.dvce_sent_tstamp <= {{ snowplow_utils.timestamp_add('day', var("snowplow__days_late_allowed", 3), 'a.dvce_created_tstamp') }} + and a.collector_tstamp >= {{ lower_limit }} + and a.collector_tstamp <= {{ upper_limit }} + and {{ snowplow_utils.app_id_filter(var("snowplow__app_id",[])) }} + and {{ snowplow_media_player.event_name_filter(var("snowplow__media_event_names", "['media_player_event']")) }} - where event_name = 'media_player_event' + qualify row_number() over (partition by a.event_id order by a.collector_tstamp) = 1 ) - select +{# select *, + dense_rank() over (partition by domain_sessionid order by start_tstamp) AS event_in_session_index + +from prep #} + +select {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, p.*, coalesce(cast(piv.weight_rate * p.duration / 100 as {{ type_int() }}), 0) as play_time_sec, - coalesce(cast(case when p.is_muted = true then piv.weight_rate * p.duration / 100 else 0 end as {{ type_int() }}), 0) as play_time_sec_muted + coalesce(cast(case when p.is_muted = TRUE then piv.weight_rate * p.duration / 100 else 0 end as {{ type_int() }}), 0) as play_time_sec_muted from prep p diff --git a/models/base/scratch/snowplow_media_player_base_new_event_limits.sql b/models/base/scratch/snowplow_media_player_base_new_event_limits.sql new file mode 100644 index 0000000..5c1a1d5 --- /dev/null +++ b/models/base/scratch/snowplow_media_player_base_new_event_limits.sql @@ -0,0 +1,24 @@ +{{ config( + post_hook=["{{snowplow_utils.print_run_limits(this)}}"], + sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')) + ) +}} + + +{%- set models_in_run = snowplow_utils.get_enabled_snowplow_models('snowplow_media_player') -%} + +{% set min_last_success, + max_last_success, + models_matched_from_manifest, + has_matched_all_models = snowplow_utils.get_incremental_manifest_status(ref('snowplow_media_player_incremental_manifest'), + models_in_run) -%} + + +{% set run_limits_query = snowplow_utils.get_run_limits(min_last_success, + max_last_success, + models_matched_from_manifest, + has_matched_all_models, + var("snowplow__start_date","2020-01-01")) -%} + + +{{ run_limits_query }} diff --git a/models/base/scratch/snowplow_media_player_base_sessions_this_run.sql b/models/base/scratch/snowplow_media_player_base_sessions_this_run.sql new file mode 100644 index 0000000..b03abc3 --- /dev/null +++ b/models/base/scratch/snowplow_media_player_base_sessions_this_run.sql @@ -0,0 +1,31 @@ +{{ + config( + tags=["this_run"], + sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')), + post_hook=[ + "{{ snowplow_utils.quarantine_sessions('snowplow_media_player', var('snowplow__max_session_days')) }}" + ], + ) +}} + +{%- set lower_limit, + upper_limit, + session_start_limit = snowplow_utils.return_base_new_event_limits(ref('snowplow_media_player_base_new_event_limits')) %} + +select + s.session_id, + s.domain_userid, + s.start_tstamp, + -- end_tstamp used in next step to limit events. When backfilling, set end_tstamp to upper_limit if end_tstamp > upper_limit. + -- This ensures we don't accidentally process events after upper_limit + case when s.end_tstamp > {{ upper_limit }} then {{ upper_limit }} else s.end_tstamp end as end_tstamp + +from {{ ref('snowplow_media_player_base_sessions_lifecycle_manifest')}} s + +where +-- General window of start_tstamps to limit table scans. Logic complicated by backfills. +-- To be within the run, session start_tstamp must be >= lower_limit - max_session_days as we limit end_tstamp in manifest to start_tstamp + max_session_days +s.start_tstamp >= {{ session_start_limit }} +and s.start_tstamp <= {{ upper_limit }} +-- Select sessions within window that either; start or finish between lower & upper limit, start and finish outside of lower and upper limits +and not (s.start_tstamp > {{ upper_limit }} or s.end_tstamp < {{ lower_limit }}) diff --git a/models/web/scratch/snowplow_media_player_pivot_base.sql b/models/base/scratch/snowplow_media_player_pivot_base.sql similarity index 62% rename from models/web/scratch/snowplow_media_player_pivot_base.sql rename to models/base/scratch/snowplow_media_player_pivot_base.sql index 16aa659..a627f00 100644 --- a/models/web/scratch/snowplow_media_player_pivot_base.sql +++ b/models/base/scratch/snowplow_media_player_pivot_base.sql @@ -11,7 +11,7 @@ with prep as ( select - {{ element }} as percent_progress + {{ element }} as percent_progress {% if not loop.last %} @@ -27,8 +27,15 @@ with prep as ( select percent_progress, - percent_progress - lag(percent_progress, 1) over(order by percent_progress) as weight_rate, - first_value(percent_progress) over(order by percent_progress rows between unbounded preceding and unbounded following) as first_item + percent_progress + - lag(percent_progress, 1) over (order by percent_progress) as weight_rate, + first_value(percent_progress) + over ( + order by + percent_progress + rows between unbounded preceding and unbounded following + ) + as first_item from prep diff --git a/models/base/src_base.yml b/models/base/src_base.yml new file mode 100644 index 0000000..b845d15 --- /dev/null +++ b/models/base/src_base.yml @@ -0,0 +1,267 @@ +version: 2 + +sources: + - name: atomic + schema: "{{ var('snowplow__atomic_schema', 'atomic') }}" + database: "{{ var('snowplow__database', target.database) if target.type not in ['databricks', 'spark'] else var('snowplow__databricks_catalog', 'hive_metastore') if target.type in ['databricks'] else var('snowplow__atomic_schema', 'atomic') }}" + tables: + - name: events + identifier: "{{ var('snowplow__events') }}" + description: '{{ doc("table_events") }}' + columns: + - name: app_id + description: '{{ doc("col_app_id") }}' + - name: platform + description: '{{ doc("col_platform") }}' + - name: etl_tstamp + description: '{{ doc("col_etl_tstamp") }}' + - name: collector_tstamp + description: '{{ doc("col_collector_tstamp") }}' + - name: dvce_created_tstamp + description: '{{ doc("col_dvce_created_tstamp") }}' + - name: event + description: '{{ doc("col_event") }}' + - name: event_id + description: '{{ doc("col_event_id") }}' + - name: txn_id + description: '{{ doc("col_txn_id") }}' + - name: name_tracker + description: '{{ doc("col_name_tracker") }}' + - name: v_tracker + description: '{{ doc("col_v_tracker") }}' + - name: v_collector + description: '{{ doc("col_v_collector") }}' + - name: v_etl + description: '{{ doc("col_v_etl") }}' + - name: user_id + description: '{{ doc("col_user_id") }}' + - name: user_ipaddress + description: '{{ doc("col_user_ipaddress") }}' + - name: user_fingerprint + description: '{{ doc("col_user_fingerprint") }}' + - name: domain_userid + description: '{{ doc("col_domain_userid") }}' + - name: domain_sessionidx + description: '{{ doc("col_domain_sessionidx") }}' + - name: network_userid + description: '{{ doc("col_network_userid") }}' + - name: geo_country + description: '{{ doc("col_geo_country") }}' + - name: geo_region + description: '{{ doc("col_geo_region") }}' + - name: geo_city + description: '{{ doc("col_geo_city") }}' + - name: geo_zipcode + description: '{{ doc("col_geo_zipcode") }}' + - name: geo_latitude + description: '{{ doc("col_geo_latitude") }}' + - name: geo_longitude + description: '{{ doc("col_geo_longitude") }}' + - name: geo_region_name + description: '{{ doc("col_geo_region_name") }}' + - name: ip_isp + description: '{{ doc("col_ip_isp") }}' + - name: ip_organization + description: '{{ doc("col_ip_organization") }}' + - name: ip_domain + description: '{{ doc("col_ip_domain") }}' + - name: ip_netspeed + description: '{{ doc("col_ip_netspeed") }}' + - name: page_url + description: '{{ doc("col_page_url") }}' + - name: page_title + description: '{{ doc("col_page_title") }}' + - name: page_referrer + description: '{{ doc("col_page_referrer") }}' + - name: page_urlscheme + description: '{{ doc("col_page_urlscheme") }}' + - name: page_urlhost + description: '{{ doc("col_page_urlhost") }}' + - name: page_urlport + description: '{{ doc("col_page_urlport") }}' + - name: page_urlpath + description: '{{ doc("col_page_urlpath") }}' + - name: page_urlquery + description: '{{ doc("col_page_urlquery") }}' + - name: page_urlfragment + description: '{{ doc("col_page_urlfragment") }}' + - name: refr_urlscheme + description: '{{ doc("col_refr_urlscheme") }}' + - name: refr_urlhost + description: '{{ doc("col_refr_urlhost") }}' + - name: refr_urlport + description: '{{ doc("col_refr_urlport") }}' + - name: refr_urlpath + description: '{{ doc("col_refr_urlpath") }}' + - name: refr_urlquery + description: '{{ doc("col_refr_urlquery") }}' + - name: refr_urlfragment + description: '{{ doc("col_refr_urlfragment") }}' + - name: refr_medium + description: '{{ doc("col_refr_medium") }}' + - name: refr_source + description: '{{ doc("col_refr_source") }}' + - name: refr_term + description: '{{ doc("col_refr_term") }}' + - name: mkt_medium + description: '{{ doc("col_mkt_medium") }}' + - name: mkt_source + description: '{{ doc("col_mkt_source") }}' + - name: mkt_term + description: '{{ doc("col_mkt_term") }}' + - name: mkt_content + description: '{{ doc("col_mkt_content") }}' + - name: mkt_campaign + description: '{{ doc("col_mkt_campaign") }}' + - name: se_category + description: '{{ doc("col_se_category") }}' + - name: se_action + description: '{{ doc("col_se_action") }}' + - name: se_label + description: '{{ doc("col_se_label") }}' + - name: se_property + description: '{{ doc("col_se_property") }}' + - name: se_value + description: '{{ doc("col_se_value") }}' + - name: tr_orderid + description: '{{ doc("col_tr_orderid") }}' + - name: tr_affiliation + description: '{{ doc("col_tr_affiliation") }}' + - name: tr_total + description: '{{ doc("col_tr_total") }}' + - name: tr_tax + description: '{{ doc("col_tr_tax") }}' + - name: tr_shipping + description: '{{ doc("col_tr_shipping") }}' + - name: tr_city + description: '{{ doc("col_tr_city") }}' + - name: tr_state + description: '{{ doc("col_tr_state") }}' + - name: tr_country + description: '{{ doc("col_tr_country") }}' + - name: ti_orderid + description: '{{ doc("col_ti_orderid") }}' + - name: ti_sku + description: '{{ doc("col_ti_sku") }}' + - name: ti_name + description: '{{ doc("col_ti_name") }}' + - name: ti_category + description: '{{ doc("col_ti_category") }}' + - name: ti_price + description: '{{ doc("col_ti_price") }}' + - name: ti_quantity + description: '{{ doc("col_ti_quantity") }}' + - name: pp_xoffset_min + description: '{{ doc("col_pp_xoffset_min") }}' + - name: pp_xoffset_max + description: '{{ doc("col_pp_xoffset_max") }}' + - name: pp_yoffset_min + description: '{{ doc("col_pp_yoffset_min") }}' + - name: pp_yoffset_max + description: '{{ doc("col_pp_yoffset_max") }}' + - name: useragent + description: '{{ doc("col_useragent") }}' + - name: br_name + description: '{{ doc("col_br_name") }}' + - name: br_family + description: '{{ doc("col_br_family") }}' + - name: br_version + description: '{{ doc("col_br_version") }}' + - name: br_type + description: '{{ doc("col_br_type") }}' + - name: br_renderengine + description: '{{ doc("col_br_renderengine") }}' + - name: br_lang + description: '{{ doc("col_br_lang") }}' + - name: br_features_pdf + description: '{{ doc("col_br_features_pdf") }}' + - name: br_features_flash + description: '{{ doc("col_br_features_flash") }}' + - name: br_features_java + description: '{{ doc("col_br_features_java") }}' + - name: br_features_director + description: '{{ doc("col_br_features_director") }}' + - name: br_features_quicktime + description: '{{ doc("col_br_features_quicktime") }}' + - name: br_features_realplayer + description: '{{ doc("col_br_features_realplayer") }}' + - name: br_features_windowsmedia + description: '{{ doc("col_br_features_windowsmedia") }}' + - name: br_features_gears + description: '{{ doc("col_br_features_gears") }}' + - name: br_features_silverlight + description: '{{ doc("col_br_features_silverlight") }}' + - name: br_cookies + description: '{{ doc("col_br_cookies") }}' + - name: br_colordepth + description: '{{ doc("col_br_colordepth") }}' + - name: br_viewwidth + description: '{{ doc("col_br_viewwidth") }}' + - name: br_viewheight + description: '{{ doc("col_br_viewheight") }}' + - name: os_name + description: '{{ doc("col_os_name") }}' + - name: os_family + description: '{{ doc("col_os_family") }}' + - name: os_manufacturer + description: '{{ doc("col_os_manufacturer") }}' + - name: os_timezone + description: '{{ doc("col_os_timezone") }}' + - name: dvce_type + description: '{{ doc("col_dvce_type") }}' + - name: dvce_ismobile + description: '{{ doc("col_dvce_ismobile") }}' + - name: dvce_screenwidth + description: '{{ doc("col_dvce_screenwidth") }}' + - name: dvce_screenheight + description: '{{ doc("col_dvce_screenheight") }}' + - name: doc_charset + description: '{{ doc("col_doc_charset") }}' + - name: doc_width + description: '{{ doc("col_doc_width") }}' + - name: doc_height + description: '{{ doc("col_doc_height") }}' + - name: tr_currency + description: '{{ doc("col_tr_currency") }}' + - name: tr_total_base + description: '{{ doc("col_tr_total_base") }}' + - name: tr_tax_base + description: '{{ doc("col_tr_tax_base") }}' + - name: tr_shipping_base + description: '{{ doc("col_tr_shipping_base") }}' + - name: ti_currency + description: '{{ doc("col_ti_currency") }}' + - name: ti_price_base + description: '{{ doc("col_ti_price_base") }}' + - name: base_currency + description: '{{ doc("col_base_currency") }}' + - name: geo_timezone + description: '{{ doc("col_geo_timezone") }}' + - name: mkt_clickid + description: '{{ doc("col_mkt_clickid") }}' + - name: mkt_network + description: '{{ doc("col_mkt_network") }}' + - name: etl_tags + description: '{{ doc("col_etl_tags") }}' + - name: dvce_sent_tstamp + description: '{{ doc("col_dvce_sent_tstamp") }}' + - name: refr_domain_userid + description: '{{ doc("col_refr_domain_userid") }}' + - name: refr_dvce_tstamp + description: '{{ doc("col_refr_dvce_tstamp") }}' + - name: domain_sessionid + description: '{{ doc("col_domain_sessionid") }}' + - name: derived_tstamp + description: '{{ doc("col_derived_tstamp") }}' + - name: event_vendor + description: '{{ doc("col_event_vendor") }}' + - name: event_name + description: '{{ doc("col_event_name") }}' + - name: event_format + description: '{{ doc("col_event_format") }}' + - name: event_version + description: '{{ doc("col_event_version") }}' + - name: event_fingerprint + description: '{{ doc("col_event_fingerprint") }}' + - name: true_tstamp + description: '{{ doc("col_true_tstamp") }}' diff --git a/models/custom/snowplow_media_player_custom.yml b/models/custom/snowplow_media_player_custom.yml index b1d2e39..ed05be9 100644 --- a/models/custom/snowplow_media_player_custom.yml +++ b/models/custom/snowplow_media_player_custom.yml @@ -2,6 +2,7 @@ version: 2 models: - name: snowplow_media_player_session_stats + +tags: "snowplow_media_player_incremental" description: '{{ doc("table_session_stats") }}' columns: - name: domain_sessionid @@ -44,6 +45,7 @@ models: - name: complete_plays description: '{{ doc("col_complete_plays") }}' - name: snowplow_media_player_user_stats + +tags: "snowplow_media_player_incremental" description: '{{ doc("table_user_stats") }}' columns: - name: domain_userid diff --git a/models/web/scratch/base_scratch.yml b/models/web/scratch/base_scratch.yml new file mode 100644 index 0000000..d9c4da8 --- /dev/null +++ b/models/web/scratch/base_scratch.yml @@ -0,0 +1,67 @@ +version: 2 + +models: + - name: snowplow_media_player_base_this_run + description: '{{ doc("table_base_this_run") }}' + columns: + - name: play_id + description: '{{ doc("col_play_id") }}' + tags: + - primary-key + tests: + - unique + - not_null + - name: page_view_id + description: '{{ doc("col_page_view_id") }}' + - name: media_id + description: '{{ doc("col_media_id") }}' + - name: media_label + description: '{{ doc("col_media_label") }}' + - name: domain_sessionid + description: '{{ doc("col_domain_sessionid") }}' + - name: domain_userid + description: '{{ doc("col_domain_userid") }}' + - name: duration + description: '{{ doc("col_duration") }}' + - name: media_type + description: '{{ doc("col_media_type") }}' + - name: media_player_type + description: '{{ doc("col_media_player_type") }}' + - name: page_referrer + description: '{{ doc("col_page_referrer") }}' + - name: page_url + description: '{{ doc("col_page_url") }}' + - name: source_url + description: '{{ doc("col_source_url") }}' + - name: geo_region_name + description: '{{ doc("col_geo_region_name") }}' + - name: br_name + description: '{{ doc("col_br_name") }}' + - name: dvce_type + description: '{{ doc("col_dvce_type") }}' + - name: os_name + description: '{{ doc("col_os_name") }}' + - name: os_timezone + description: '{{ doc("col_os_timezone") }}' + - name: start_tstamp + description: '{{ doc("col_start_tstamp") }}' + - name: end_tstamp + description: '{{ doc("col_end_tstamp") }}' + - name: play_time_sec + description: '{{ doc("col_play_time_sec") }}' + - name: play_time_sec_muted + description: '{{ doc("col_play_time_sec_muted") }}' + - name: is_played + description: '{{ doc("col_is_played") }}' + - name: is_valid_play + description: '{{ doc("col_is_valid_play") }}' + - name: is_complete_play + description: '{{ doc("col_is_complete_play") }}' + - name: avg_playback_rate + description: '{{ doc("col_avg_playback_rate") }}' + - name: retention_rate + description: '{{ doc("col_retention_rate") }}' + - name: seeks + description: '{{ doc("col_seeks") }}' + - name: percent_progress_reached + description: '{{ doc("col_percent_progress_reached") }}' diff --git a/models/web/scratch/interactions_this_run/bigquery/snowplow_media_player_interactions_this_run.sql b/models/web/scratch/interactions_this_run/bigquery/snowplow_media_player_interactions_this_run.sql deleted file mode 100644 index f3256f1..0000000 --- a/models/web/scratch/interactions_this_run/bigquery/snowplow_media_player_interactions_this_run.sql +++ /dev/null @@ -1,268 +0,0 @@ -{{ - config( - materialized='table', - tags=["this_run"], - ) -}} - -with prep as ( - - select - e.event_id, - e.page_view_id, - e.domain_sessionid, - e.domain_userid, - e.page_referrer, - e.page_url, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'label', 'dtype': 'string'}], - col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as media_label, - round(cast({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'duration', 'dtype': 'int'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as float64)) as duration, - e.geo_region_name, - e.br_name, - e.dvce_type, - e.os_name, - e.os_timezone, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'type', 'dtype': 'string'}], - col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as event_type, - e.derived_tstamp as start_tstamp, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'current_time', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as player_current_time, - coalesce(cast({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'playback_rate', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as float64), 1) as playback_rate, - case when {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'type', 'dtype': 'string'}], - col_prefix='unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} = 'ended' - then 100 - else safe_cast({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'percent_progress', 'dtype': 'int'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as int64) end as percent_progress, - cast({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'muted', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as boolean) as is_muted, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'is_live', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as is_live, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'loop', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as loop, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'volume', 'dtype': 'string'}], - col_prefix='contexts_com_snowplowanalytics_snowplow_media_player_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as volume, - {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} - {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both need to be enabled for modelling html5 video tracking data.") }} - - {% elif var("snowplow__enable_youtube") %} - {% if var("snowplow__enable_whatwg_media") %} - coalesce({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'player_id', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'html_id', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}) as media_id, - case when {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'player_id', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} is not null - then 'com.youtube-youtube' - when {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'html_id', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} is not null - then 'org.whatwg-media_element' - else 'unknown' end as media_player_type, - coalesce({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'url', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'current_src', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}) as source_url, - case when {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'media_type', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - coalesce({{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'playback_quality', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}, {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'video_width', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_video_element_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}||'x'||{{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'video_height', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_video_element_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}) as playback_quality - {% else %} - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'playback_quality', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e')}}, - {% endif %} - {% else %} - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'player_id', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as media_id, - 'com.youtube-youtube' as media_player_type, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'url', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as source_url, - 'video' as media_type, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'playback_quality', 'dtype': 'string'}], - col_prefix='contexts_com_youtube_youtube_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e')}} - {% endif %} - - {% elif var("snowplow__enable_whatwg_media") %} - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'html_id', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as media_id, - 'org.whatwg-media_element' as media_player_type, - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'current_src', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as source_url, - case when {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'media_type', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_media_element_1_', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - {{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'video_width', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_video_element_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}}||'x'||{{ snowplow_utils.get_optional_fields( - enabled= true, - fields=[{'field': 'video_height', 'dtype': 'string'}], - col_prefix='contexts_org_whatwg_video_element_1', - relation=ref('snowplow_web_base_events_this_run'), - relation_alias='e', - include_field_alias=false)}} as playback_quality - {% else %} - 'N/A' as playback_quality - {% endif %} - - {% else %} - {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} - {% endif %} - - from {{ ref("snowplow_web_base_events_this_run") }} as e - - where event_name = 'media_player_event' -) - - select - {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, - p.*, - coalesce(cast(piv.weight_rate * p.duration / 100 as {{ type_int() }}), 0) as play_time_sec, - coalesce(cast(case when p.is_muted = true then piv.weight_rate * p.duration / 100 else 0 end as {{ type_int() }}), 0) as play_time_sec_muted - - from prep p - - left join {{ ref("snowplow_media_player_pivot_base") }} piv - on p.percent_progress = piv.percent_progress diff --git a/models/web/scratch/interactions_this_run/databricks/snowplow_media_player_interactions_this_run.sql b/models/web/scratch/interactions_this_run/databricks/snowplow_media_player_interactions_this_run.sql deleted file mode 100644 index 6af129d..0000000 --- a/models/web/scratch/interactions_this_run/databricks/snowplow_media_player_interactions_this_run.sql +++ /dev/null @@ -1,83 +0,0 @@ -{{ - config( - materialized='table', - tags=["this_run"], - sql_header=snowplow_utils.set_query_tag(var('snowplow__query_tag', 'snowplow_dbt')) - ) -}} - -with prep as ( - - select - e.event_id, - e.page_view_id, - e.domain_sessionid, - e.domain_userid, - e.page_referrer, - e.page_url, - e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.label::STRING as media_label, - round(contexts_com_snowplowanalytics_snowplow_media_player_1[0].duration::float) as duration, - e.geo_region_name, - e.br_name, - e.dvce_type, - e.os_name, - e.os_timezone, - e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.type::STRING as event_type, - e.derived_tstamp as start_tstamp, - contexts_com_snowplowanalytics_snowplow_media_player_1[0].current_time::float as player_current_time, - coalesce(contexts_com_snowplowanalytics_snowplow_media_player_1[0].playback_rate::STRING, 1) as playback_rate, - case when e.unstruct_event_com_snowplowanalytics_snowplow_media_player_event_1.type::STRING = 'ended' then 100 else contexts_com_snowplowanalytics_snowplow_media_player_1[0].percent_progress::int end percent_progress, - contexts_com_snowplowanalytics_snowplow_media_player_1[0].muted::STRING as is_muted, - contexts_com_snowplowanalytics_snowplow_media_player_1[0].is_live::STRING as is_live, - contexts_com_snowplowanalytics_snowplow_media_player_1[0].loop::STRING as loop, - contexts_com_snowplowanalytics_snowplow_media_player_1[0].volume::STRING as volume, - {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} - {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both need to be enabled for modelling html5 video tracking data.") }} - {% elif var("snowplow__enable_youtube") %} - {% if var("snowplow__enable_whatwg_media") %} - coalesce(e.contexts_com_youtube_youtube_1[0].player_id::STRING, e.contexts_org_whatwg_media_element_1[0].html_id::STRING) as media_id, - case when e.contexts_com_youtube_youtube_1[0].player_id is not null then 'com.youtube-youtube' - when e.contexts_org_whatwg_media_element_1[0].html_id::STRING is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, - coalesce(e.contexts_com_youtube_youtube_1[0].url::STRING, e.contexts_org_whatwg_media_element_1[0].current_src::STRING) as source_url, - case when e.contexts_org_whatwg_media_element_1[0].media_type::STRING = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - coalesce(e.contexts_com_youtube_youtube_1[0].playback_quality::STRING, e.contexts_org_whatwg_video_element_1[0].video_width::STRING||'x'||e.contexts_org_whatwg_video_element_1[0].video_height::STRING) as playback_quality - {% else %} - e.contexts_com_youtube_youtube_1[0].playback_quality::STRING - {% endif %} - {% else %} - e.contexts_com_youtube_youtube_1[0].player_id::STRING as media_id, - 'com.youtube-youtube' as media_player_type, - e.contexts_com_youtube_youtube_1[0].url::STRING as source_url, - 'video' as media_type, - e.contexts_com_youtube_youtube_1[0].playback_quality::STRING - {% endif %} - {% elif var("snowplow__enable_whatwg_media") %} - e.contexts_org_whatwg_media_element_1[0].html_id::STRING as media_id, - 'org.whatwg-media_element' as media_player_type, - e.contexts_org_whatwg_media_element_1[0].current_src::STRING as source_url, - case when e.contexts_org_whatwg_media_element_1[0].media_type::STRING = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - e.contexts_org_whatwg_video_element_1[0].video_width::STRING||'x'||e.contexts_org_whatwg_video_element_1[0].video_height::STRING as playback_quality - {% else %} - 'N/A' as playback_quality - {% endif %} - {% else %} - {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} - {% endif %} - - from {{ ref("snowplow_web_base_events_this_run") }} as e - - where event_name = 'media_player_event' -) - - select - {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, - p.*, - coalesce(cast(round(piv.weight_rate * p.duration / 100) as {{ type_int() }}), 0) as play_time_sec, - coalesce(cast(case when p.is_muted = true then round(piv.weight_rate * p.duration / 100) else 0 end as {{ type_int() }}), 0) as play_time_sec_muted - - from prep p - - left join {{ ref("snowplow_media_player_pivot_base") }} piv - on p.percent_progress = piv.percent_progress diff --git a/models/web/scratch/interactions_this_run/redshift_postgres/snowplow_media_player_interactions_this_run.sql b/models/web/scratch/interactions_this_run/redshift_postgres/snowplow_media_player_interactions_this_run.sql deleted file mode 100644 index 16dc3df..0000000 --- a/models/web/scratch/interactions_this_run/redshift_postgres/snowplow_media_player_interactions_this_run.sql +++ /dev/null @@ -1,207 +0,0 @@ -{{ - config( - materialized='table', - tags=["this_run"], - sort = 'start_tstamp', - dist = 'event_id' - ) -}} - -{%- set lower_limit, upper_limit = snowplow_utils.return_limits_from_model(ref('snowplow_web_base_sessions_this_run'), - 'start_tstamp', - 'end_tstamp') %} - -with mpe_context as ( - - select - root_id, - root_tstamp, - label, - type, - row_number() over (partition by root_id order by root_tstamp) dedupe_index - - from {{ var('snowplow__media_player_event_context') }} - - where root_tstamp between {{ lower_limit }} and {{ upper_limit }} - -) - -, mp_context as ( - - select - root_id, - root_tstamp, - duration, - playback_rate, - current_time, - percent_progress, - muted, - is_live, - loop, - volume, - row_number() over (partition by root_id order by root_tstamp) dedupe_index - - from {{ var('snowplow__media_player_context') }} - - where root_tstamp between {{ lower_limit }} and {{ upper_limit }} - -) - -{% if var("snowplow__enable_youtube") %} - -, yt_context as ( - - select - root_id, - root_tstamp, - player_id, - url, - playback_quality, - row_number() over (partition by root_id order by root_tstamp) dedupe_index - - from {{ var('snowplow__youtube_context') }} - - where root_tstamp between {{ lower_limit }} and {{ upper_limit }} - -) - -{% endif %} - -{% if var("snowplow__enable_whatwg_media") %} - -, me_context as ( - -select - root_id, - root_tstamp, - media_type, - current_src, - html_id, - row_number() over (partition by root_id order by root_tstamp) dedupe_index - -from {{ var('snowplow__html5_media_element_context') }} - -where root_tstamp between {{ lower_limit }} and {{ upper_limit }} - -) - -{% endif %} - -{% if var("snowplow__enable_whatwg_video") %} - -, ve_context as ( - -select - root_id, - root_tstamp, - video_width, - video_height, - row_number() over (partition by root_id order by root_tstamp) dedupe_index - -from {{ var('snowplow__html5_video_element_context') }} - -where root_tstamp between {{ lower_limit }} and {{ upper_limit }} - -) - -{% endif %} - -, prep as ( - - select - e.event_id, - e.page_view_id, - e.domain_sessionid, - e.domain_userid, - e.page_referrer, - e.page_url, - mpe.label as media_label, - round(mp.duration) as duration, - e.geo_region_name, - e.br_name, - e.dvce_type, - e.os_name, - e.os_timezone, - mpe.type as event_type, - e.derived_tstamp as start_tstamp, - mp.current_time as player_current_time, - coalesce(mp.playback_rate, 1) as playback_rate, - case when mpe.type = 'ended' then 100 else mp.percent_progress end percent_progress, - mp.muted as is_muted, - mp.is_live, - mp.loop, - mp.volume, - {% if var("snowplow__enable_whatwg_media") is false and var("snowplow__enable_whatwg_video") %} - {{ exceptions.raise_compiler_error("variable: snowplow__enable_whatwg_video is enabled but variable: snowplow__enable_whatwg_media is not, both needs to be enabled for modelling html5 video tracking data.") }} - {% elif var("snowplow__enable_youtube") %} - {% if var("snowplow__enable_whatwg_media") %} - coalesce(y.player_id, me.html_id) as media_id, - case when y.player_id is not null then 'com.youtube-youtube' when me.html_id is not null then 'org.whatwg-media_element' else 'unknown' end as media_player_type, - coalesce(y.url, me.current_src) as source_url, - case when me.media_type = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - coalesce(y.playback_quality, ve.video_width||'x'||ve.video_height) as playback_quality - {% else %} - y.playback_quality - {% endif %} - {% else %} - y.player_id as media_id, - 'com.youtube-youtube' as media_player_type, - y.url as source_url, - 'video' as media_type, - y.playback_quality - {% endif %} - {% elif var("snowplow__enable_whatwg_media") %} - me.html_id as media_id, - 'org.whatwg-media_element' as media_player_type, - me.current_src as source_url, - case when me.media_type = 'audio' then 'audio' else 'video' end as media_type, - {% if var("snowplow__enable_whatwg_video") %} - ve.video_width||'x'||ve.video_height as playback_quality - {% else %} - 'N/A' as playback_quality - {% endif %} - {% else %} - {{ exceptions.raise_compiler_error("No media context enabled. Please enable as many of the following variables as required: snowplow__enable_youtube, snowplow__enable_whatwg_media, snowplow__enable_whatwg_video") }} - {% endif %} - - from {{ ref("snowplow_web_base_events_this_run") }} as e - - inner join mpe_context as mpe - on mpe.root_id = e.event_id and mpe.root_tstamp = e.collector_tstamp - and mpe.dedupe_index = 1 - - inner join mp_context as mp - on mp.root_id = e.event_id and mp.root_tstamp = e.collector_tstamp - and mp.dedupe_index = 1 - - {% if var("snowplow__enable_youtube") %} - left join yt_context as y - on y.root_id = e.event_id and y.root_tstamp = e.collector_tstamp - and y.dedupe_index = 1 - {% endif %} - - {% if var("snowplow__enable_whatwg_media") %} - left join me_context as me - on me.root_id = e.event_id and me.root_tstamp = e.collector_tstamp - and me.dedupe_index = 1 - {% endif %} - - {% if var("snowplow__enable_whatwg_video") %} - left join ve_context as ve - on ve.root_id = e.event_id and ve.root_tstamp = e.collector_tstamp - and ve.dedupe_index = 1 - {% endif %} - -) - - select - {{ dbt_utils.generate_surrogate_key(['p.page_view_id', 'p.media_id' ]) }} play_id, - p.*, - coalesce(cast(round(piv.weight_rate * p.duration / 100) as {{ type_int() }}), 0) as play_time_sec, - coalesce(cast(case when p.is_muted then round(piv.weight_rate * p.duration / 100) end as {{ type_int() }}), 0) as play_time_sec_muted - - from prep p - - left join {{ ref("snowplow_media_player_pivot_base") }} piv - on p.percent_progress = piv.percent_progress diff --git a/models/web/scratch/snowplow_media_player_base_this_run.sql b/models/web/scratch/snowplow_media_player_base_this_run.sql index ce4f53d..a6e76f7 100644 --- a/models/web/scratch/snowplow_media_player_base_this_run.sql +++ b/models/web/scratch/snowplow_media_player_base_this_run.sql @@ -36,17 +36,22 @@ with prep as ( min(start_tstamp) as start_tstamp, max(start_tstamp) as end_tstamp, sum(case when i.event_type = 'play' then 1 else 0 end) as plays, - sum(case when i.event_type in ('seek', 'seeked') then 1 else 0 end) as seeks, + sum(case when i.event_type in ('seek', 'seeked') then 1 else 0 end) + as seeks, sum(i.play_time_sec) as play_time_sec, sum(i.play_time_sec_muted) as play_time_sec_muted, - coalesce(sum(i.playback_rate * i.play_time_sec) / nullif(sum(i.play_time_sec), 0), max(i.playback_rate)) as avg_playback_rate, + coalesce( + sum(i.playback_rate * i.play_time_sec) / nullif(sum(i.play_time_sec), 0), + max(i.playback_rate) + ) as avg_playback_rate, {{ snowplow_utils.get_string_agg('percent_progress', 'i', sort_numeric=true) }} as percent_progress_reached, - min(case when i.event_type in ('seek', 'seeked') then start_tstamp end) as first_seek_time, + min(case when i.event_type in ('seek', 'seeked') then start_tstamp end) + as first_seek_time, max(i.percent_progress) as max_percent_progress - from {{ ref('snowplow_media_player_interactions_this_run') }} as i + from {{ ref('snowplow_media_player_base_events_this_run') }} as i - group by 1,2,3,4,5,6,8,9,10,11,13,14,15,16,17 + group by 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 17 ) @@ -54,7 +59,9 @@ with prep as ( select *, - row_number() over (partition by play_id order by start_tstamp) as duplicate_count + row_number() + over (partition by play_id order by start_tstamp) + as duplicate_count from prep @@ -62,18 +69,20 @@ with prep as ( , retention_rate as ( - select - d.play_id, - max(i.percent_progress) as retention_rate + select + d.play_id, + max(i.percent_progress) as retention_rate - from dedupe d + from dedupe as d - inner join {{ ref("snowplow_media_player_interactions_this_run") }} i + inner join {{ ref("snowplow_media_player_base_events_this_run") }} as i on i.play_id = d.play_id - where i.percent_progress is not null and (i.start_tstamp <= d.first_seek_time or d.first_seek_time is null) + where + i.percent_progress is not null + and (i.start_tstamp <= d.first_seek_time or d.first_seek_time is null) - group by 1 + group by 1 ) @@ -84,7 +93,7 @@ with prep as ( f.media_id, max(f.duration) as duration - from {{ ref('snowplow_media_player_interactions_this_run') }} as f + from {{ ref('snowplow_media_player_base_events_this_run') }} as f group by 1 @@ -113,26 +122,41 @@ select d.play_time_sec, d.play_time_sec_muted, d.plays > 0 as is_played, - case when d.play_time_sec > {{ var("snowplow__valid_play_sec") }} then true else false end is_valid_play, - case when play_time_sec / nullif(f.duration, 0) >= {{ var("snowplow__complete_play_rate") }} then true else false end as is_complete_play, + case + when d.play_time_sec > {{ var("snowplow__valid_play_sec") }} then true else + false + end + as is_valid_play, + case + when + d.play_time_sec / nullif(f.duration, 0) + >= {{ var("snowplow__complete_play_rate") }} + then true else + false + end as is_complete_play, cast(d.avg_playback_rate as {{ type_float() }}) as avg_playback_rate, - cast(coalesce(case when r.retention_rate > d.max_percent_progress - then d.max_percent_progress / cast(100 as {{ type_float() }}) - else r.retention_rate / cast(100 as {{ type_float() }}) - end, 0) as {{ type_float() }}) as retention_rate, -- to correct incorrect result due to duplicate session_id (one removed) + cast(coalesce(case + when r.retention_rate > d.max_percent_progress + then d.max_percent_progress / cast(100 as {{ type_float() }}) + else r.retention_rate / cast(100 as {{ type_float() }}) + -- to correct incorrect result due to duplicate session_id (one removed) + end, 0) as {{ type_float() }}) as retention_rate, d.seeks, - case when d.percent_progress_reached = '' then null else d.percent_progress_reached end as percent_progress_reached + case + when d.percent_progress_reached = '' then null else + d.percent_progress_reached + end as percent_progress_reached {% if target.type in ['databricks', 'spark'] -%} , date(start_tstamp) as start_tstamp_date {%- endif %} -from dedupe d +from dedupe as d -left join retention_rate r -on r.play_id = d.play_id +left join retention_rate as r + on r.play_id = d.play_id -left join duration_fix f -on f.media_id = d.media_id +left join duration_fix as f + on f.media_id = d.media_id where d.duplicate_count = 1 diff --git a/models/web/snowplow_media_player.yml b/models/web/snowplow_media_player.yml index 16fc81d..b638bee 100644 --- a/models/web/snowplow_media_player.yml +++ b/models/web/snowplow_media_player.yml @@ -2,6 +2,7 @@ version: 2 models: - name: snowplow_media_player_base + +tags: "snowplow_media_player_incremental" description: '{{ doc("table_base") }}' columns: - name: play_id @@ -66,6 +67,7 @@ models: - name: percent_progress_reached description: '{{ doc("col_percent_progress_reached") }}' - name: snowplow_media_player_plays_by_pageview + +tags: "snowplow_media_player_incremental" description: '{{ doc("table_plays_by_pageview") }}' columns: - name: play_id diff --git a/models/web/snowplow_media_player_base.sql b/models/web/snowplow_media_player_base.sql index 352b3e6..e77cd49 100644 --- a/models/web/snowplow_media_player_base.sql +++ b/models/web/snowplow_media_player_base.sql @@ -24,4 +24,5 @@ select * from {{ ref('snowplow_media_player_base_this_run') }} -where {{ snowplow_utils.is_run_with_new_events('snowplow_web') }} --returns false if run doesn't contain new events. +--returns false if run doesn't contain new events. +where {{ snowplow_utils.is_run_with_new_events('snowplow_media_player') }} diff --git a/models/web/snowplow_media_player_media_stats.sql b/models/web/snowplow_media_player_media_stats.sql index d3c412b..49cfd34 100644 --- a/models/web/snowplow_media_player_media_stats.sql +++ b/models/web/snowplow_media_player_media_stats.sql @@ -224,49 +224,49 @@ select p.avg_retention_rate, l.last_base_tstamp, -{% if target.type in ['databricks', 'spark'] -%} - date(first_play) as first_play_date, -{%- endif %} + {% if target.type in ['databricks', 'spark'] -%} + date(first_play) as first_play_date, + {%- endif %} -{% if is_incremental() %} + {% if is_incremental() %} - {% for element in get_percentage_boundaries(var("snowplow__percent_progress_boundaries")) %} - coalesce(cast(a._{{ element }}_percent_reached as {{ type_int() }}), 0) as _{{ element }}_percent_reached - {% if not loop.last %} - , - {% endif %} - {% endfor %} + {% for element in get_percentage_boundaries(var("snowplow__percent_progress_boundaries")) %} + coalesce(cast(a._{{ element }}_percent_reached as {{ type_int() }}), 0) as _{{ element }}_percent_reached + {% if not loop.last %} + , + {% endif %} + {% endfor %} -{% else %} + {% else %} - {{ dbt_utils.pivot( - column='un.value_reached', - values=dbt_utils.get_column_values( table=ref('snowplow_media_player_pivot_base'), column='percent_progress', default=[]) | sort, - alias=True, - agg='sum', - cmp='=', - prefix='_', - suffix='_percent_reached', - quote_identifiers=FALSE - ) }} + {{ dbt_utils.pivot( + column='un.value_reached', + values=dbt_utils.get_column_values( table=ref('snowplow_media_player_pivot_base'), column='percent_progress', default=[]) | sort, + alias=True, + agg='sum', + cmp='=', + prefix='_', + suffix='_percent_reached', + quote_identifiers=FALSE + ) }} -{% endif %} + {% endif %} -from prep p + from prep p -left join (select max(last_base_tstamp) as last_base_tstamp from prep ) l -on 1 = 1 + left join (select max(last_base_tstamp) as last_base_tstamp from prep ) l + on 1 = 1 -{% if is_incremental() %} + {% if is_incremental() %} -left join addition a -on a.media_id = p.media_id + left join addition a + on a.media_id = p.media_id -{% else %} + {% else %} -left join unnesting un -on un.media_id = p.media_id + left join unnesting un + on un.media_id = p.media_id -group by 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 + group by 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 {% endif %} diff --git a/packages.yml b/packages.yml index 05bf035..556ec4f 100644 --- a/packages.yml +++ b/packages.yml @@ -1,3 +1,3 @@ packages: - - package: snowplow/snowplow_web - version: [">=0.14.0", "<0.16.0"] + - package: snowplow/snowplow_utils + version: [">=0.14.1", "<0.15.0"] diff --git a/selectors.yml b/selectors.yml index 485dfb6..9b2bebe 100644 --- a/selectors.yml +++ b/selectors.yml @@ -39,7 +39,7 @@ selectors: - method: path value: models - method: tag - value: snowplow_web_incremental + value: snowplow_media_player_incremental - method: package value: snowplow_media_player - method: tag @@ -67,21 +67,21 @@ selectors: - method: package value: snowplow_web - method: tag - value: snowplow_web_incremental + value: snowplow_media_player_incremental - method: package value: snowplow_media_player - method: tag value: snowplow_media_player - - name: snowplow_web - # description: > - # Suggested node selection when running the Snowplow Web package together with the Media Player package. - # Runs: - # - All Snowplow Web and Media Player models. - # - All custom models in your dbt project, tagged with `snowplow_web_incremental`. - definition: - union: - - method: package - value: snowplow_web - - method: tag - value: snowplow_web_incremental + # - name: snowplow_web + # # description: > + # # Suggested node selection when running the Snowplow Web package together with the Media Player package. + # # Runs: + # # - All Snowplow Web and Media Player models. + # # - All custom models in your dbt project, tagged with `snowplow_web_incremental`. + # definition: + # union: + # - method: package + # value: snowplow_web + # - method: tag + # value: snowplow_web_incremental