├── renovate.json ├── package.json ├── index.js ├── templates ├── route.js └── directive.js ├── .gitignore └── readme.md /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-event-trace", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "clark", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "axios": "^0.17.0", 9 | "vue": "~2.4.2" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | 3 | const resolvePath = (...args) => resolve(__dirname, ...args) 4 | 5 | module.exports = function trace (options) { 6 | if (options.pageApi) { 7 | this.addPlugin({ 8 | src: resolvePath('templates/route.js'), 9 | fileName: 'event-trace-route.js', 10 | options 11 | }) 12 | } 13 | if (options.elementApi) { 14 | this.addPlugin({ 15 | src: resolvePath('templates/directive.js'), 16 | fileName: 'event-trace-directive.js', 17 | options 18 | }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /templates/route.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export default ({ app: { router } }, inject) => { 4 | // eslint-disable-next-line no-constant-condition 5 | if (!'<%= options.pageApi %>') { 6 | console.warn('Warn: pageApi is not found in event-trace module options') 7 | return 8 | } 9 | router.afterEach(function (to, from) { 10 | const info = { 11 | from: from.name, 12 | fromPath: from.path, 13 | to: to.name, 14 | toPath: to.path, 15 | params: to.params, 16 | time: new Date() 17 | } 18 | axios.post('<%= options.pageApi %>', info) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (http://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | 65 | # End of https://www.gitignore.io/api/node 66 | 67 | yarn.lock 68 | -------------------------------------------------------------------------------- /templates/directive.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import axios from 'axios' 3 | 4 | class TraceEvent { 5 | bind (el, binding, vnode) { 6 | // eslint-disable-next-line no-constant-condition 7 | if (!'<%= options.elementApi %>') { 8 | console.warn('Warn: elementApi is not found in event-trace module options') 9 | return 10 | } 11 | if (!binding) return 12 | if (typeof binding.value !== 'object') { 13 | console.warn('v-trace value is not a object in ' + binding.rawName) 14 | return 15 | } 16 | 17 | // passing parameters as object 18 | const {category, action, label, value, nodeId} = binding.value 19 | const info = {category, action, label, value, nodeId, time: new Date()} 20 | 21 | // use modifier as events 22 | const events = Object.keys(binding.modifiers).map(modifier => { 23 | if (binding.modifiers[modifier]) { 24 | return modifier 25 | } 26 | }) 27 | 28 | // addEventListener for each event, call trackEvent api 29 | if (!events.length) events.push('click') // listen click event by default 30 | events.forEach((event) => { 31 | el.addEventListener(event, () => { 32 | axios.post('<%= options.elementApi %>', info) 33 | }, false) 34 | }) 35 | } 36 | } 37 | 38 | Vue.directive('trace', new TraceEvent()) 39 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Module for event trace in Nuxt.js 2 | 3 | ### Install 4 | 5 | ```bash 6 | $ yarn add nuxt-event-trace 7 | ``` 8 | 9 | Add module into `nuxt.config.js`. 10 | 11 | 1. `elementApi` is api url for dom elements tracking. 12 | 1. `pageApi` is api url for pages routing tracking. 13 | 14 | ```js 15 | modules: [ 16 | ['./client/modules/event-trace', { 17 | elementApi: "http://example.com/api/trace", 18 | pageApi: "http://example.com/route/trace" 19 | }] 20 | ] 21 | ``` 22 | 23 | ### Trace on routes 24 | 25 | If defined `pageApi`, all routes will be logged after routing. 26 | 27 | ### Trace on component 28 | 29 | Define `v-trace` directive on `component`. 30 | 31 | ```html 32 | 34 | 35 | 37 | 38 | ``` 39 | 40 | 1. Value items include: `category`, `action`, `label`, `value`, `nodeId` 41 | 1. [Event Type](https://developer.mozilla.org/en-US/docs/Web/Events) is defined as modifiers, `click` is default if no type specified. 42 | 43 | ```html 44 | 45 | 46 | 47 | ``` 48 | --------------------------------------------------------------------------------