log.js
import sa from 'sa-sdk-javascript'
let Log = {}
/**
* 发送 1 条统计事件,把这条统计事件分发到神策
*
*/
Log.push = function (args) {
// debug('log.push', args);
// if (isBrowser === false) { return; }
if (args[1] == '') {
sa.track(args[0])
} else {
try {
let paramObj = compileParam(args[1])
sa.track(args[0], paramObj)
} catch (e) {
}
}
// sa.track(args[0], args[3])
};
let compileParam = function (param) {
if (param == '' || param == null || param == undefined) return param;
let arr = param.split("&");
let obj = {}
arr.forEach(function (v, i) {
let arr1 = v.split("=");
obj[arr1[0]] = arr1[1];
})
return obj;
}
/**
* 生成1个统计事件监听函数,要么是focus、要么是click,更多的事件需要的时候再支持
*
* @param {String} _eventType 需要处理哪种类型的事件
* @param {Boolean} isGaEnabled 透传的参数
* @return Function
*/
var getEventHandler = function (_eventType) {
return function (eventTarget) {
// // 拿到事件发生的节点
// var eventTarget = e.target,
var eventType = eventTarget.getAttribute('vd-event-type') || 'click',
eventParam = eventTarget.getAttribute('vd-event-param') || '',
eventName = eventTarget.getAttribute('vd-event-name').replace(/(^\s*)|(\s*$)/g, '');
if (eventName && eventType === _eventType) { // vd-event-name 是否为空,并且类型匹配
// 获取页面层级属性
var scopes = [eventName];
var event = getParents(eventTarget, 'vd-event-scope')
if (event !== undefined) {
var scope = event.getAttribute('vd-event-scope').replace(/(^\s*)|(\s*$)/g, '')
if (scope) { // vd-event-scope 是否为空
scopes.push(scope);
}
// scopes [scope,name]
scopes.reverse();
Log.push([scopes.join('_'), eventParam]);
}
}
};
};
/**
* 原生获取父元素
* @param {*} el
* @param {*} attr 属性,符合条件的属性
*/
function getParents(el, attr) {
var parent = el.parentNode
if (parent && parent.nodeName == 'BODY') {
if (parent.hasAttribute(attr)) {
return parent
} else {
return
}
} else {
if (parent) {
// list.push(parent)
// 避免有多个vd-event-scope
if (parent.hasAttribute(attr)) {
return parent
} else {
return getParents(parent, attr)
}
} else {
return
}
}
}
/**
* 利用事件委托对所有需要自动发送统计事件的节点进行监听,只能初始化一次
*/
var isInitialized = false;
Log.init = function () {
var ndBody = document.querySelector('body');
var ndNoBubble = document.querySelectorAll('[vd-event-no-bubble]');
// 处理可以冒泡的节点
console.log(ndBody);
console.log(ndNoBubble);
ndBody.addEventListener('click', function (e) {
// 处理选择符(这样不好,如果一个a标签里面有图片和文字,点击到其他应该触发到a标签的)
if (e.target.hasAttribute('vd-event-name')) {
getEventHandler('click')(e.target)
} else {
var event = getParents(e.target, 'vd-event-name')
if (event !== undefined) {
getEventHandler('click')(event)
}
}
});
// 处理无法冒泡到顶层的结点点击
if (ndNoBubble && ndNoBubble.length > 0) {
ndNoBubble.addEventListener('click', getEventHandler('click'));
}
// }
};
export default Log
main,js
import Vue from 'vue'
import App from './App';
import router from './router';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import sa from 'sa-sdk-javascript'
import Log from './common/log';
// const user_id = VueCookies.get('id') // 这个是必须要有唯一的id,可以取用户id
sa.init({
server_url: '/sensors/api/v1/default/53f48d27f5ed6e701241d7548093274533d0af3d9d2ae80740a629836897900d', // 替换成自己的神策地址
heatmap: {
//是否开启点击图,默认 default 表示开启,自动采集 $WebClick 事件,可以设置 'not_collect' 表示关闭
clickmap:'not_collect',
show_log: true, // 打印console,自己配置,可以看到自己是否踩点成功,以及
//是否开启触达注意力图,默认 default 表示开启,自动采集 $WebStay 事件,可以设置 'not_collect' 表示关闭
scroll_notice_map:'not_collect'
},
// is_track_single_page:true,
send_type: 'ajax',
});
const user_id = sa.store.getDistinctId();
sa.login(user_id);
// if (window.$config.env == 'prod') { // 这个地方是看自己的需求加判断添加
// 神策路由监控页面跳转
router.afterEach((to,from) => {
Vue.nextTick(() => {
sa.quick("autoTrackSinglePage");
});
})
// 点击事件统计
Log.init()
// }
Vue.config.productionTip = false
Vue.use(ElementUI);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
login.vue
<template>
<div class="login" vd-event-scope="login">
<h1>登录页面</h1>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="useName">
<el-input v-model="ruleForm.useName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
// 需要埋点的地方写下这些代码
<el-button type="primary" @click="submitForm('ruleForm')"
vd-event-name="WebClick_submit" vd-event-type="click">提交</el-button>
<el-button @click="resetForm('ruleForm')"
vd-event-name="WebClick_reset" vd-event-type="click">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
index.vue
<template>
<div class="index" vd-event-scope="index">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="活动名称" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="ruleForm.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间" required>
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker type="date" placeholder="选择日期" v-model="ruleForm.date1" style="width: 100%;"></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker placeholder="选择时间" v-model="ruleForm.date2" style="width: 100%;"></el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="即时配送" prop="delivery">
<el-switch v-model="ruleForm.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源" prop="resource">
<el-radio-group v-model="ruleForm.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式" prop="desc">
<el-input type="textarea" v-model="ruleForm.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')"
vd-event-name="WebClick_submit" vd-event-type="click">立即创建</el-button>
<el-button @click="toTable()"
vd-event-name="WebClick_toTable" vd-event-type="click" :vd-event-param="param">前往table页</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
// import sensors from'../common/sensors';
export default {
data() {
return {
start: new Date(),
path: this.$route.path,
ruleForm: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
rules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
region: [
{ required: true, message: '请选择活动区域', trigger: 'change' }
],
date1: [
{ type: 'date', required: true, message: '请选择日期', trigger: 'change' }
],
date2: [
{ type: 'date', required: true, message: '请选择时间', trigger: 'change' }
],
type: [
{ type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
],
resource: [
{ required: true, message: '请选择活动资源', trigger: 'change' }
],
desc: [
{ required: true, message: '请填写活动形式', trigger: 'blur' }
]
}
};
},
created() {
console.log(this.$route.path)
this.loadHandler();
// if ('onpageshow' in window) {
// this.addEvent(window, 'pageshow', this.loadHandler);
// this.addEvent(window, 'pagehide', this.unloadHandler);
// } else {
// this.addEvent(window, 'load', this.loadHandler);
// this.addEvent(window, 'unload', this.unloadHandler);
// }
},
computed() {
// param() {
// return {
// pageStayTime: this.unloadHandler(),
// pageUrl: this.$route.path
// }
// }
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
toTable(formName) {
//跳转前调用页面停留时间函数
this.unloadHandler();
this.$router.push({ name: 'table' });
},
// 页面停留时间
loadHandler(e) {
console.log("start")
this.start = new Date();
},
unloadHandler (e) {
var end = new Date();
// 如果用户一直不关闭页面,可能出现超大值,可以根据业务需要处理,例如设置一个上限
var duration = (end.getTime() - this.start.getTime()) / 1000;
return duration;
// 定义一个记录页面停留时间的事件pageView,并且保存需要的属性(停留时间和当前页面的地址)
console.log(this.$route.path)
// sensors.track('pageclose', {
// pageStayTime: duration,
// pageUrl: this.$route.path
// });
},
// addEvent(target, type, listener) {
// if (window.addEventListener) {
// target.addEventListener(type, listener, false);
// } else {
// target.attachEvent('on' + type, listener);
// }
// },
}
}
</script>
<style>
.demo-ruleForm {
width: 500px;
margin: 100px auto;
border: 1px solid #ccc;
padding: 20px;
text-align: left;
}
</style>