Commit cbdc69d1 authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '7424-create-a-generic-event-listener-for-tracking-clicks-on-gitlab-com' into 'master'

Resolve "Create a generic event listener for tracking clicks on GitLab.com"

Closes #7424

See merge request gitlab-org/gitlab-ee!7403
parents 9b5e7122 036958b7
- active_tab = local_assigns.fetch(:active_tab, 'blank')
- track_label = local_assigns.fetch(:track_label, 'import_project')
.project-import
.form-group.import-btn-container.clearfix
......@@ -7,60 +8,62 @@
.import-buttons
- if gitlab_project_import_enabled?
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
= link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
= link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_export" } do
= icon('gitlab', text: 'GitLab export')
- if github_import_enabled?
%div
= link_to new_import_github_path, class: 'btn js-import-github' do
= link_to new_import_github_path, class: 'btn js-import-github', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "github" } do
= icon('github', text: 'GitHub')
- if bitbucket_import_enabled?
%div
= link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do
= link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}",
data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_cloud" } do
= icon('bitbucket', text: 'Bitbucket Cloud')
- unless bitbucket_import_configured?
= render 'bitbucket_import_modal'
- if bitbucket_server_import_enabled?
%div
= link_to status_import_bitbucket_server_path, class: "btn import_bitbucket" do
= link_to status_import_bitbucket_server_path, class: "btn import_bitbucket", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_server" } do
= icon('bitbucket-square', text: 'Bitbucket Server')
%div
- if gitlab_import_enabled?
%div
= link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do
= link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}",
data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_com" } do
= icon('gitlab', text: 'GitLab.com')
- unless gitlab_import_configured?
= render 'gitlab_import_modal'
- if google_code_import_enabled?
%div
= link_to new_import_google_code_path, class: 'btn import_google_code' do
= link_to new_import_google_code_path, class: 'btn import_google_code', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "google_code" } do
= icon('google', text: 'Google Code')
- if fogbugz_import_enabled?
%div
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "fogbugz" } do
= icon('bug', text: 'Fogbugz')
- if gitea_import_enabled?
%div
= link_to new_import_gitea_path, class: 'btn import_gitea' do
= link_to new_import_gitea_path, class: 'btn import_gitea', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitea" } do
= custom_icon('go_logo')
Gitea
- if git_import_enabled?
%div
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' } }
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active', track_label: "#{track_label}" , track_event: "click_button", track_property: "repo_url" } }
= icon('git', text: 'Repo by URL')
- if manifest_import_enabled?
%div
= link_to new_import_manifest_path, class: 'btn import_manifest' do
= link_to new_import_manifest_path, class: 'btn import_manifest', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "manifest_file" } do
= icon('file-text-o', text: 'Manifest file')
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
= form_for @project, html: { class: 'new_project' } do |f|
%hr
= render "shared/import_form", f: f
= render 'new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true
= render 'new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true, track_label: track_label
- visibility_level = params.dig(:project, :visibility_level) || default_project_visibility
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
- hide_init_with_readme = local_assigns.fetch(:hide_init_with_readme, false)
- track_label = local_assigns.fetch(:track_label, 'blank_project')
.row{ id: project_name_id }
= f.hidden_field :ci_cd_only, value: ci_cd_only
.form-group.project-name.col-sm-12
= f.label :name, class: 'label-bold' do
%span= _("Project name")
= f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true
= f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_name", track_value: "" }
.form-group.project-path.col-sm-6
= f.label :namespace_id, class: 'label-bold' do
%span= s_("Project URL")
......@@ -22,7 +23,7 @@
display_path: true,
extra_group: namespace_id),
{},
{ class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1})
{ class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_path", track_value: "" }})
- else
.input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
......@@ -42,7 +43,7 @@
= f.label :description, class: 'label-bold' do
Project description
%span (optional)
= f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250
= f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_description", track_value: "" }
= f.label :visibility_level, class: 'label-bold' do
Visibility Level
......@@ -53,12 +54,12 @@
.form-group.row.initialize-with-readme-setting
%div{ :class => "col-sm-12" }
.form-check
= check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input'
= check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme" }
= label_tag 'project[initialize_with_readme]', class: 'form-check-label' do
.option-title
%strong Initialize repository with a README
.option-description
Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.
= f.submit 'Create project', class: "btn btn-success project-submit", tabindex: 4
= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel'
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4, data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "cancel" }
......@@ -5,4 +5,4 @@
.project-fields-form
= render 'projects/project_templates/project_fields_form'
= render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true
= render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true, track_label: "create_from_template"
......@@ -34,15 +34,15 @@
.col-lg-9.js-toggle-container
%ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
%a.nav-link.active{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' }
%a.nav-link.active{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab', track_label: 'blank_project', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Blank project
%span.d-block.d-sm-none Blank
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' }
%a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab', track_label: 'create_from_template', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Create from template
%span.d-block.d-sm-none Template
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' }
%a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab', track_label: 'import_project', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Import project
%span.d-block.d-sm-none Import
-# EE-specific start
......
......@@ -10,8 +10,10 @@
= template.description
.controls.d-flex.align-items-center
%label.btn.btn-success.template-button.choose-template.append-right-10.append-bottom-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name,
data: { track_label: "create_from_template", track_property: "template_use", track_event: "click_button" } }
%span
= _("Use template")
%a.btn.btn-default{ href: template.preview, rel: 'noopener noreferrer', target: '_blank' }
%a.btn.btn-default{ href: template.preview, rel: 'noopener noreferrer', target: '_blank',
data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: template.name } }
= _("Preview")
......@@ -3,7 +3,8 @@
- restricted = restricted_visibility_levels.include?(level)
- disabled = disallowed || restricted
.form-check{ class: [('disabled' if disabled), ('restricted' if restricted)] }
= form.radio_button model_method, level, checked: (selected_level == level), disabled: disabled, class: 'form-check-input'
= form.radio_button model_method, level, checked: (selected_level == level), disabled: disabled, class: 'form-check-input',
data: { track_label: "blank_project", track_event: "activate_form_input", track_property: "#{model_method}", track_value: "#{level}" }
= form.label "#{model_method}_#{level}", class: 'form-check-label' do
= visibility_level_icon(level)
.option-title
......
import '~/pages/projects/new/index';
import initCustomProjectTemplates from 'ee/projects/custom_project_templates';
import bindTrackEvents from 'ee/projects/track_project_new';
document.addEventListener('DOMContentLoaded', initCustomProjectTemplates);
document.addEventListener('DOMContentLoaded', () => {
initCustomProjectTemplates();
bindTrackEvents('.js-toggle-container');
});
import Stats from 'ee/stats';
const bindTrackEvents = (container) => {
Stats.bindTrackableContainer(container);
};
export default bindTrackEvents;
import $ from 'jquery';
const snowPlowEnabled = () => typeof window.snowplow === 'function';
const trackEvent = (category, eventName, additionalData = { label: '', property: '', value: '' }) => {
if (!snowPlowEnabled()) {
return;
}
if (!category || !eventName) {
return;
}
const { label, property, value } = additionalData;
try {
window.snowplow(
'trackStructEvent',
category,
eventName,
label,
property,
value,
);
} catch (e) {
// do nothing
}
};
const bindTrackableContainer = (container = '', category = document.body.dataset.page) => {
if (!snowPlowEnabled()) {
return;
}
const clickHandler = (e) => {
const target = e.currentTarget;
const label = target.getAttribute('data-track-label');
const property = target.getAttribute('data-track-property') || '';
const eventName = target.getAttribute('data-track-event');
let value = target.value || '';
// overrides value for checkboxes
if (target.type === 'checkbox') {
value = target.checked;
}
// overrides value if data-track_value is set
if (typeof target.getAttribute('data-track-value') !== 'undefined' && target.getAttribute('data-track-value') !== null) {
value = target.getAttribute('data-track-value');
}
trackEvent(category, eventName, { label, property, value });
};
const trackableElements = document.querySelectorAll(`${container} [data-track-label]`);
trackableElements.forEach(element => {
element.addEventListener('click', (e) => clickHandler(e));
});
// jquery required for select2 events
// see: https://github.com/select2/select2/issues/4686#issuecomment-264747428
$(`${container} .select2[data-track-label]`).on('click', (e) => clickHandler(e));
};
export default {
trackEvent,
bindTrackableContainer,
};
......@@ -14,7 +14,8 @@
post: true,
contexts: {
webPage: true,
}
},
stateStorageStrategy: "localStorage"
});
window.snowplow('enableActivityTracking', 30, 30);
......
- return unless ci_cd_projects_available?
- track_label = local_assigns.fetch(:track_label, 'cicd_for_external_repo')
.tab-pane.js-toggle-container{ id: 'ci-cd-project-pane', class: active_when(active_tab == 'ci_cd_only'), role: 'tabpanel' }
= form_for @project, html: { class: 'new_project' } do |f|
......@@ -18,14 +19,14 @@
.import-buttons
%div
- if github_import_enabled?
= link_to new_import_github_path(ci_cd_only: true), class: 'btn js-import-github' do
= link_to new_import_github_path(ci_cd_only: true), class: 'btn js-import-github', data: { track_label: "#{track_label}", track_property: 'github', track_event: "click_button" } do
= icon('github', text: 'GitHub')
%div
- if git_import_enabled?
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' } }
%button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active', track_label: "#{track_label}", track_property: 'repo_url', track_event: "click_button" } }
= icon('git', text: _('Repo by URL'))
.col-lg-12
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'ci_cd_only') }
%hr
= render "shared/import_form", f: f, ci_cd_only: true
= render 'new_project_fields', f: f, project_name_id: "import-url-name", ci_cd_only: true, hide_init_with_readme: true
= render 'new_project_fields', f: f, project_name_id: "import-url-name", ci_cd_only: true, hide_init_with_readme: true, track_label: track_label
- return unless ci_cd_projects_available?
%li{ class: active_when(active_tab == 'ci_cd_only'), role: 'presentation' }
%a{ href: '#ci-cd-project-pane', id: 'ci-cd-project-tab', data: { toggle: 'tab' }, role: 'tab' }
%li.nav-item{ class: active_when(active_tab == 'ci_cd_only'), role: 'presentation' }
%a.nav-link{ href: '#ci-cd-project-pane', id: 'ci-cd-project-tab', data: { toggle: 'tab', track_label: 'cicd_for_external_repo', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block
= _('CI/CD for external repo')
%span.d-block.d-sm-none
......
......@@ -21,7 +21,7 @@
.project-fields-form
= render 'projects/project_templates/project_fields_form'
= f.hidden_field(:use_custom_template, value: false)
= render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true
= render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true, track_label: "create_from_template"
- else
= render_ce 'projects/project_templates', f: f
---
title: Create a generic JS function that we can apply to being able to track arbitrary events
merge_request: 7403
author:
type: other
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment