diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-10 18:18:16 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-10 18:18:16 +0000 |
commit | e0277d5393d958865fdec470176ac5874edded06 (patch) | |
tree | f867094e393909ef822e354b1c72997ec5102f6f /doc/development/snowplow | |
parent | 74d9798736a89f07e047698e5e32964829bf8859 (diff) | |
download | gitlab-ce-e0277d5393d958865fdec470176ac5874edded06.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc/development/snowplow')
-rw-r--r-- | doc/development/snowplow/implementation.md | 170 | ||||
-rw-r--r-- | doc/development/snowplow/index.md | 1 | ||||
-rw-r--r-- | doc/development/snowplow/schemas.md | 28 |
3 files changed, 122 insertions, 77 deletions
diff --git a/doc/development/snowplow/implementation.md b/doc/development/snowplow/implementation.md index 3f038dc74ca..d35413cfd5f 100644 --- a/doc/development/snowplow/implementation.md +++ b/doc/development/snowplow/implementation.md @@ -18,21 +18,27 @@ to track custom events. For the recommended frontend tracking implementation, see [Usage recommendations](#usage-recommendations). +Structured events and page views include the [`gitlab_standard`](schemas.md#gitlab_standard) +context, using the `window.gl.snowplowStandardContext` object which includes +[default data](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/views/layouts/_snowplow.html.haml) +as base. This object can be modified for any subsequent structured event fired, +although it's not recommended. + Tracking implementations must have an `action` and a `category`. You can provide additional -categories from the [structured event taxonomy](index.md#structured-event-taxonomy) with an `extra` object -that accepts key-value pairs. +properties from the [structured event taxonomy](index.md#structured-event-taxonomy), in +addition to an `extra` object that accepts key-value pairs. -| Field | Type | Default value | Description | +| Property | Type | Default value | Description | |:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `category` | string | `document.body.dataset.page` | Page or subsection of a page in which events are captured. | -| `action` | string | generic | Action the user is taking. Clicks must be `click` and activations must be `activate`. For example, focusing a form field is `activate_form_input`, and clicking a button is `click_button`. | -| `data` | object | `{}` | Additional data such as `label`, `property`, `value`, `context` as described in [Structured event taxonomy](index.md#structured-event-taxonomy), and `extra` (key-value pairs object). | +| `action` | string | `'generic'` | Action the user is taking. Clicks must be `click` and activations must be `activate`. For example, focusing a form field is `activate_form_input`, and clicking a button is `click_button`. | +| `data` | object | `{}` | Additional data such as `label`, `property`, `value` as described in [Structured event taxonomy](index.md#structured-event-taxonomy), `context` for custom contexts, and `extra` (key-value pairs object). | ### Usage recommendations - Use [data attributes](#implement-data-attribute-tracking) on HTML elements that emit `click`, `show.bs.dropdown`, or `hide.bs.dropdown` events. -- Use the [Vue mixin](#implement-vue-component-tracking) for tracking custom events, or if the supported events for data attributes are not propagating. -- Use the [tracking class](#implement-raw-javascript-tracking) when tracking raw JavaScript files. +- Use the [Vue mixin](#implement-vue-component-tracking) for tracking custom events, or if the supported events for data attributes are not propagating. For example, clickable components that don't emit `click`. +- Use the [tracking class](#implement-raw-javascript-tracking) when tracking in vanilla JavaScript files. ### Implement data attribute tracking @@ -41,7 +47,10 @@ To implement tracking for HAML or Vue templates, add a [`data-track` attribute]( The following example shows `data-track-*` attributes assigned to a button: ```haml -%button.btn{ data: { track_action: "click_button", track_label: "template_preview", track_property: "my-template" } } +%button.btn{ data: { track: { action: "click_button", label: "template_preview", property: "my-template" } } } + +// or +// %button.btn{ data: { track_action: "click_button", track_label: "template_preview", track_property: "my-template" } } ``` ```html @@ -62,7 +71,7 @@ The following example shows `data-track-*` attributes assigned to a button: | `data-track-property` | false | Any additional property of the element, or object being acted on. | | `data-track-value` | false | Describes a numeric value (decimal) directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. | | `data-track-extra` | false | A key-value pair object passed as a valid JSON string. This attribute is added to the `extra` property in our [`gitlab_standard`](schemas.md#gitlab_standard) schema. | -| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](index.md#structured-event-taxonomy). | +| `data-track-context` | false | To append a custom context object, passed as a valid JSON string. | #### Event listeners @@ -74,12 +83,19 @@ If click events stop propagating, you must implement listeners and [Vue componen #### Helper methods -Use the following Ruby helper: +You can use the following Ruby helper: ```ruby tracking_attrs(label, action, property) # { data: { track_label... } } +``` +You can also use it on HAML templates: + +```haml %button{ **tracking_attrs('main_navigation', 'click_button', 'navigation') } + +// When adding additional data +// %button{ data: { platform: "...", **tracking_attrs('main_navigation', 'click_button', 'navigation') } } ``` If you use the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/helpers/tab_helper.rb#L76), you must wrap `html_options` under the `html_options` keyword argument. If you @@ -91,7 +107,7 @@ use the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2. track_action: "click_button" }) # Good -= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: += nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "explore_groups", track_action: "click_button" } }) # Good (other helpers) @@ -101,63 +117,64 @@ track_action: "click_button" }) ### Implement Vue component tracking -For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event` -static method and the `track` method. You can specify tracking options in `data` or `computed`. -These options override any defaults and allow the values to be dynamic from props or based on state. - -Several default options are passed when an event is tracked from the component: +For custom event tracking, use the [Vue mixin](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/tracking.js#L207). It exposes `Tracking.event` as the `track` method. +You can specify tracking options by creating a `tracking` data object or +computed property, and as a second parameter: `this.track('click_button', opts)`. +These options override any defaults and allow the values to be dynamic from props or based on state: -- `category`: If you don't specify, by default `document.body.dataset.page` is used. -- `label` -- `property` -- `value` +| Property | Type | Default | Example | +| -- | -- | -- | -- | +| `category` | string | `document.body.dataset.page` | `'code_quality_walkthrough'` | +| `label` | string | `''` | `'process_start_button'` | +| `property` | string | `''` | `'asc'` or `'desc'` | +| `value` | integer | `undefined` | `0`, `1`, `500` | +| `extra` | object | `{}` | `{ selectedVariant: this.variant }` | To implement Vue component tracking: -1. Import the `Tracking` library and request a `mixin`: +1. Import the `Tracking` library and call the `mixin` method: ```javascript import Tracking from '~/tracking'; - const trackingMixin = Tracking.mixin; - ``` -1. Provide categories to track the event from the component. For example, to track all events in a -component with a label, use the `label` category: + const trackingMixin = Tracking.mixin(); - ```javascript - import Tracking from '~/tracking'; - const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); + // Optionally provide default properties + // const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); ``` -1. In the component, declare the Vue `mixin`: +1. Use the mixin in the component: ```javascript export default { mixins: [trackingMixin], - // ...[component implementation]... + // Or + // mixins: [Tracking.mixin()], + // mixins: [Tracking.mixin({ label: 'right_sidebar' })], + data() { return { expanded: false, - tracking: { - label: 'left_sidebar', - }, }; }, }; ``` -1. To receive event data as a tracking object or computed property: - - Declare it in the `data` function. Use a `tracking` object when default event properties are dynamic or provided at runtime: +1. You can specify tracking options in by creating a `tracking` data object +or computed property: ```javascript export default { name: 'RightSidebar', + mixins: [Tracking.mixin()], + data() { return { + expanded: false, + variant: '', tracking: { label: 'right_sidebar', - // category: '', // property: '', // value: '', // experiment: '', @@ -165,18 +182,28 @@ component with a label, use the `label` category: }, }; }, + + // Or + // computed: { + // tracking() { + // return { + // property: this.variant, + // extra: { expanded: this.expanded }, + // }; + // }, + // }, }; ``` - - Declare it in the event data in the `track` function. This object merges with any previously provided options: +1. Call the `track` method. Tracking options can be passed as the second parameter: - ```javascript - this.track('click_button', { - label: 'right_sidebar', - }); - ``` + ```javascript + this.track('click_button', { + label: 'right_sidebar', + }); + ``` -1. Optional. Use the `track` method in a template: + Or use the `track` method in the template: ```html <template> @@ -185,55 +212,67 @@ component with a label, use the `label` category: <div v-if="expanded"> <p>Hello world!</p> - <button @click="track('click_action')">Track another event</button> + <button @click="track('click_button')">Track another event</button> </div> </div> </template> ``` -The following example shows an implementation of Vue component tracking: +#### Testing example ```javascript export default { - name: 'RightSidebar', - mixins: [Tracking.mixin({ label: 'right_sidebar' })], + name: 'CountDropdown', + + mixins: [Tracking.mixin({ label: 'count_dropdown' })], + data() { return { - expanded: false, + variant: 'counter', + count: 0, }; }, + methods: { - toggle() { - this.expanded = !this.expanded; - // Additional data will be merged, like `value` below - this.track('click_toggle', { value: Number(this.expanded) }); - } - } + handleChange({ target }) { + const { variant } = this; + + this.count = Number(target.value); + + this.track('change_value', { + value: this.count, + extra: { variant } + }); + }, + }, }; ``` -#### Testing example - ```javascript import { mockTracking } from 'helpers/tracking_helper'; // mockTracking(category, documentOverride, spyMethod) -describe('RightSidebar.vue', () => { +describe('CountDropdown.vue', () => { let trackingSpy; let wrapper; + ... + beforeEach(() => { trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); }); - const findToggle = () => wrapper.find('[data-testid="toggle"]'); + const findDropdown = () => wrapper.find('[data-testid="dropdown"]'); - it('tracks turning off toggle', () => { - findToggle().trigger('click'); + it('tracks change event', () => { + const dropdown = findDropdown(); + dropdown.element.value = 30; + dropdown.trigger('change'); - expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_toggle', { - label: 'right_sidebar', - value: 0, + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'change_value', { + value: 30, + label: 'count_dropdown', + extra: { variant: 'counter' }, }); }); }); @@ -241,7 +280,8 @@ describe('RightSidebar.vue', () => { ### Implement raw JavaScript tracking -To call custom event tracking and instrumentation directly from the JavaScript file, call the `Tracking.event` static function. +To track from a vanilla JavaScript file, use the `Tracking.event` static function +(calls [`dispatchSnowplowEvent`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/tracking/dispatch_snowplow_event.js)). The following example demonstrates tracking a click on a button by manually calling `Tracking.event`. @@ -251,7 +291,7 @@ import Tracking from '~/tracking'; const button = document.getElementById('create_from_template_button'); button.addEventListener('click', () => { - Tracking.event('dashboard:projects:index', 'click_button', { + Tracking.event(undefined, 'click_button', { label: 'create_from_template', property: 'template_preview', extra: { diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md index 4b5dd82315b..29f4514a21e 100644 --- a/doc/development/snowplow/index.md +++ b/doc/development/snowplow/index.md @@ -72,6 +72,7 @@ sequenceDiagram GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk end GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose + Note over GitLab.com Snowplow Collector, S3 Bucket: Pseudonymization S3 Bucket->>Snowflake DW: Import data Snowflake DW->>Snowflake DW: Transform data using dbt Snowflake DW->>Sisense Dashboards: Data available for querying diff --git a/doc/development/snowplow/schemas.md b/doc/development/snowplow/schemas.md index eb57e7d98a5..63864c9329b 100644 --- a/doc/development/snowplow/schemas.md +++ b/doc/development/snowplow/schemas.md @@ -12,19 +12,23 @@ This page provides Snowplow schema reference for GitLab events. We are including the [`gitlab_standard` schema](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/) with every event. See [Standardize Snowplow Schema](https://gitlab.com/groups/gitlab-org/-/epics/5218) for details. -The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) class represents this schema in the application. +The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/tracking/standard_context.rb) +class represents this schema in the application. Some properties are automatically populated for [frontend](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/views/layouts/_snowplow.html.haml) +events. -| Field Name | Required | Type | Description | -|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------| -| `project_id` | **{dotted-circle}** | integer | | -| `namespace_id` | **{dotted-circle}** | integer | | -| `user_id` | **{dotted-circle}** | integer | User database record ID attribute. This file undergoes a pseudonymization process at the collector level. | -| `context_generated_at` | **{dotted-circle}** | string (date time format) | Timestamp indicating when context was generated. | -| `environment` | **{check-circle}** | string (max 32 chars) | Name of the source environment, such as `production` or `staging` | -| `source` | **{check-circle}** | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` | -| `plan` | **{dotted-circle}** | string (max 32 chars) | Name of the plan for the namespace, such as `free`, `premium`, or `ultimate`. Automatically picked from the `namespace`. | -| `google_analytics_id` | **{dotted-circle}** | string (max 32 chars) | Google Analytics ID, present when set from our marketing sites. | -| `extra` | **{dotted-circle}** | JSON | Any additional data associated with the event, in the form of key-value pairs | +| Field Name | Required | Default value | Type | Description | +|----------------|:-------------------:|-----------------------|--|---------------------------------------------------------------------------------------------| +| `project_id` | **{dotted-circle}** | Current project ID * | integer | | +| `namespace_id` | **{dotted-circle}** | Current group/namespace ID * | integer | | +| `user_id` | **{dotted-circle}** | Current user ID * | integer | User database record ID attribute. This file undergoes a pseudonymization process at the collector level. | +| `context_generated_at` | **{dotted-circle}** | Current timestamp | string (date time format) | Timestamp indicating when context was generated. | +| `environment` | **{check-circle}** | Current environment | string (max 32 chars) | Name of the source environment, such as `production` or `staging` | +| `source` | **{check-circle}** | Event source | string (max 32 chars) | Name of the source application, such as `gitlab-rails` or `gitlab-javascript` | +| `plan` | **{dotted-circle}** | Current namespace plan * | string (max 32 chars) | Name of the plan for the namespace, such as `free`, `premium`, or `ultimate`. Automatically picked from the `namespace`. | +| `google_analytics_id` | **{dotted-circle}** | GA ID value * | string (max 32 chars) | Google Analytics ID, present when set from our marketing sites. | +| `extra` | **{dotted-circle}** | | JSON | Any additional data associated with the event, in the form of key-value pairs | + +_\* Default value present for frontend events only_ ## Default Schema |