From df440ddc7949295d1eff6d954b472dacf0eae4d0 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Tue, 14 Jul 2020 16:14:29 +0100 Subject: [PATCH] Some more analytics logic --- src/nginxconfig/templates/app.vue | 34 ++++++------ .../templates/domain_sections/presets.vue | 3 ++ src/nginxconfig/templates/setup.vue | 3 ++ src/nginxconfig/util/analytics.js | 54 +++++++++++++++++++ src/nginxconfig/util/camel_to_snake.js | 27 ++++++++++ 5 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 src/nginxconfig/util/analytics.js create mode 100644 src/nginxconfig/util/camel_to_snake.js diff --git a/src/nginxconfig/templates/app.vue b/src/nginxconfig/templates/app.vue index 7381f2c..07e6f58 100644 --- a/src/nginxconfig/templates/app.vue +++ b/src/nginxconfig/templates/app.vue @@ -101,11 +101,15 @@ THE SOFTWARE. import escape from 'escape-html'; import Header from 'do-vue/src/templates/header'; import diff from 'files-diff'; + import isChanged from '../util/is_changed'; import importData from '../util/import_data'; import isObject from '../util/is_object'; + import analytics from '../util/analytics'; + import i18n from '../i18n'; import generators from '../generators'; + import Domain from './domain'; import Global from './global'; import Setup from './setup'; @@ -163,7 +167,7 @@ THE SOFTWARE. importData(query, this.$data.domains, this.$data.global, this.$nextTick); // Send an initial GA event for column mode - this.splitColumnEvent(false); + this.splitColumnEvent(); }, methods: { changes(index) { @@ -191,10 +195,16 @@ THE SOFTWARE. // Store this.$data.domains.push(data); this.$data.active = this.$data.domains.length - 1; + + // GA + analytics('add_site', 'Sites', undefined, this.activeDomains.length); }, remove(index) { this.$set(this.$data.domains, index, null); if (this.$data.active === index) this.$data.active = this.$data.domains.findIndex(d => d !== null); + + // GA + analytics('remove_site', 'Sites', undefined, this.activeDomains.length); }, checkChange(oldConf) { // If nothing has changed for a tick, we can use the config files @@ -219,7 +229,7 @@ THE SOFTWARE. const diffConf = diff(newConf, oldConf, { highlightFunction: value => `${value}`, }); - this.$data.confFilesOutput = Object.values(diffConf).map(({ name, content }) => { + this.$data.confFilesOutput = diffConf ? Object.values(diffConf).map(({ name, content }) => { const diffName = name.filter(x => !x.removed).map(x => x.value).join(''); const confName = `${escape(this.$data.global.nginx.nginxConfigDirectory.computed)}/${diffName}`; const diffContent = content.filter(x => !x.removed).map(x => x.value).join(''); @@ -229,27 +239,15 @@ THE SOFTWARE. diffContent, `${sha2_256(confName)}-${sha2_256(diffContent)}`, ]; - }); + }) : []; this.$nextTick(() => this.$data.confWatcherWaiting = false); }, splitColumnToggle() { this.$data.splitColumn = !this.$data.splitColumn; - this.splitColumnEvent(true); + this.splitColumnEvent(); }, - splitColumnEvent(interact) { - if (window.ga) { - const tracker = window.ga.getAll()[0]; - if (tracker) { - tracker.send({ - hitType: 'event', - eventCategory: 'Button', - eventAction: 'toggle', - eventLabel: 'Split Column', - eventValue: Number(this.$data.splitColumn), - nonInteraction: !interact, - }); - } - } + splitColumnEvent() { + analytics('toggle_split_column', 'Button', undefined, Number(this.$data.splitColumn)); }, }, }; diff --git a/src/nginxconfig/templates/domain_sections/presets.vue b/src/nginxconfig/templates/domain_sections/presets.vue index d34fe0e..d308bd4 100644 --- a/src/nginxconfig/templates/domain_sections/presets.vue +++ b/src/nginxconfig/templates/domain_sections/presets.vue @@ -56,6 +56,8 @@ THE SOFTWARE. import i18n from '../../i18n'; import delegatedFromDefaults from '../../util/delegated_from_defaults'; import computedFromDefaults from '../../util/computed_from_defaults'; + import analytics from '../../util/analytics'; + import camelToSnake from '../../util/camel_to_snake'; const defaults = { frontend: { @@ -190,6 +192,7 @@ THE SOFTWARE. setPreset(key) { // Set that we're using this preset Object.keys(this.$props.data).forEach(preset => this[preset] = preset === key); + analytics(`apply_${camelToSnake(key)}`, 'Presets'); // Restore some specific defaults first this.$parent.resetValue('server', 'domain'); diff --git a/src/nginxconfig/templates/setup.vue b/src/nginxconfig/templates/setup.vue index a22f7e0..90e9165 100644 --- a/src/nginxconfig/templates/setup.vue +++ b/src/nginxconfig/templates/setup.vue @@ -64,6 +64,7 @@ THE SOFTWARE. import Tar from 'memory-tar-create'; import ClipboardJS from 'clipboard'; import i18n from '../i18n'; + import analytics from '../util/analytics'; import * as Sections from './setup_sections'; const tabs = Object.values(Sections); @@ -124,9 +125,11 @@ THE SOFTWARE. return new Tar(data).gz(); }, downloadTar() { + analytics('download_tar', 'Download', this.tarName); this.tarContents().download(this.tarName); }, copyTar() { + analytics('download_base64', 'Download', this.tarName); const path = `${this.$props.data.global.nginx.nginxConfigDirectory.computed}/${this.tarName}`; return this.tarContents().base64(path); }, diff --git a/src/nginxconfig/util/analytics.js b/src/nginxconfig/util/analytics.js new file mode 100644 index 0000000..66e6b70 --- /dev/null +++ b/src/nginxconfig/util/analytics.js @@ -0,0 +1,54 @@ +/* +Copyright 2020 DigitalOcean + +This code is licensed under the MIT License. +You may obtain a copy of the License at +https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +export default (action, category, label, value) => { + console.log({ + eventCategory: category, + eventAction: action, + eventLabel: label, + eventValue: value, + }); + + // gtag.js + if (window.gtag) { + return window.gtag('event', action, { + event_category: category, + event_label: label, + value, + }); + } + + // analytics.js + if (window.ga) { + return window.ga('send', { + hitType: 'event', + eventCategory: category, + eventAction: action, + eventLabel: label, + eventValue: value, + }); + } +}; diff --git a/src/nginxconfig/util/camel_to_snake.js b/src/nginxconfig/util/camel_to_snake.js new file mode 100644 index 0000000..c8e6c75 --- /dev/null +++ b/src/nginxconfig/util/camel_to_snake.js @@ -0,0 +1,27 @@ +/* +Copyright 2020 DigitalOcean + +This code is licensed under the MIT License. +You may obtain a copy of the License at +https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +export default str => str.replace(/[\w]([A-Z])/g, m => `${m[0]}_${m[1]}`).toLowerCase();