feat: 新增神策数据埋点和广告页面功能
This commit is contained in:
28
src/main.ts
28
src/main.ts
@@ -15,29 +15,44 @@ import './assets/css/main.scss';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import 'swiper/css/pagination';
|
||||
import { sensorsData } from './utils/plugins/sa';
|
||||
import { isCollectUrl } from './utils/url/tools';
|
||||
import { sensorsData } from '@/utils/plugins/sa';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
if (import.meta.env.VITE_APP_ENV !== 'production') {
|
||||
const vconsole = new VConsole();
|
||||
/* const vconsole = */ new VConsole();
|
||||
// app.use(vconsole);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
sa: any;
|
||||
onAndroidBack: (() => void) | null;
|
||||
appBridge?: any;
|
||||
}
|
||||
}
|
||||
|
||||
const sa = {
|
||||
register: false,
|
||||
instance: window.sa || null
|
||||
};
|
||||
|
||||
// 定义路由是否可以返回的判断
|
||||
const routerCanGoBack = () => {
|
||||
const position = router.options.history.state?.position;
|
||||
return typeof position === 'number' && position > 0;
|
||||
};
|
||||
router.beforeEach((to, from, next) => {
|
||||
// 神策数据埋点
|
||||
if (!sa.register && sessionStorage.getItem('userInfo')) {
|
||||
sa.instance = window.sa;
|
||||
// 检测是否使用神策的登陆
|
||||
const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '');
|
||||
sa.instance.setOnceProfile({ loginID: userInfo.userCode });
|
||||
|
||||
sa.register = true;
|
||||
}
|
||||
|
||||
if (to.meta?.title) document.title = to.meta.title as string;
|
||||
|
||||
if (to.query.digitalYiliToken) {
|
||||
@@ -58,5 +73,10 @@ router.beforeEach((to, from, next) => {
|
||||
app.use(createPinia());
|
||||
app.use(router);
|
||||
// 神策数据插件
|
||||
app.use(sensorsData());
|
||||
app.use(sensorsData(), {
|
||||
// 测试环境
|
||||
server_url: 'https://digitaldmo.yili.com/sa?project=sensorstest'
|
||||
// 正式环境
|
||||
// server_url: 'https://digitaldmo.yili.com/sa?project=YIP'
|
||||
});
|
||||
app.mount('#app');
|
||||
|
||||
@@ -2,7 +2,6 @@ import { createRouter, createWebHistory } from 'vue-router';
|
||||
import layout from '@/layouts/index.vue';
|
||||
import Design from '@/views/Design/Index.vue';
|
||||
import Redirect from '@/layouts/redirect.vue';
|
||||
import type { title } from 'process';
|
||||
import { getWXShareConfig } from '@/utils/share';
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import type { App } from 'vue';
|
||||
import sensors from '@/assets/js/sa-sdk-javascript/dist/web/sensorsdata.es6.js';
|
||||
|
||||
// 定义神策数据插件选项接口
|
||||
interface SensorsDataOptions {
|
||||
// 可以根据需要添加具体的选项属性
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export function sensorsData() {
|
||||
return {
|
||||
install(app: App, options?: SensorsDataOptions) {
|
||||
// console.log(`sensorsData install`);
|
||||
sensors.init({
|
||||
// server_url: '数据接收地址',
|
||||
show_log: true,
|
||||
// 单页面配置,默认关闭。开启后自动监听 URL 有变化就会触发 $pageview 事件
|
||||
is_track_single_page: false,
|
||||
use_client_time: true,
|
||||
send_type: 'beacon',
|
||||
heatmap: {
|
||||
//是否开启点击图,default 表示开启,自动采集 $WebClick 事件,可以设置 'not_collect' 表示关闭。
|
||||
clickmap: 'not_collect',
|
||||
//是否开启触达图,not_collect 表示关闭,不会自动采集 $WebStay 事件,可以设置 'default' 表示开启。
|
||||
scroll_notice_map: 'not_collect'
|
||||
},
|
||||
...options
|
||||
});
|
||||
|
||||
// sensors.quick('autoTrack'); //用于采集 $pageview 事件。
|
||||
|
||||
// 注册公共属性
|
||||
sensors.registerPage({
|
||||
platform: 'h5',
|
||||
current_url: location.href,
|
||||
referrer: document.referrer
|
||||
});
|
||||
// app.config.globalProperties.$sensorsData = sensors;
|
||||
app.provide('sensors', sensors);
|
||||
|
||||
// 注册 sa 点击跟踪指令
|
||||
registerDirective(app);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册 sa 点击跟踪指令
|
||||
* @param app 应用实例
|
||||
*/
|
||||
function registerDirective(app: App) {
|
||||
app.directive('saTrack', {
|
||||
mounted(el, binding) {
|
||||
el.addEventListener('click', () => {
|
||||
// console.log(`sa track`, binding);
|
||||
sensors.track(binding.arg as string, binding.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
71
src/utils/plugins/sa/index.ts
Normal file
71
src/utils/plugins/sa/index.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import type { App } from 'vue';
|
||||
import sensors from './dist/v2/sensorsdata.es6';
|
||||
|
||||
/**
|
||||
* 神策数据 SDK
|
||||
*/
|
||||
export type Sensors = typeof sensors;
|
||||
|
||||
/**
|
||||
* 创建神策数据插件
|
||||
*/
|
||||
export function sensorsData() {
|
||||
return {
|
||||
install(app: App, options: any) {
|
||||
// 初始化神策 SDK
|
||||
sensors.init({
|
||||
show_log: true,
|
||||
is_track_single_page: false,
|
||||
use_client_time: true,
|
||||
send_type: 'beacon',
|
||||
heatmap: {
|
||||
clickmap: 'not_collect',
|
||||
scroll_notice_map: 'not_collect'
|
||||
},
|
||||
...(options || {})
|
||||
});
|
||||
|
||||
// 注册页面公共属性
|
||||
sensors.registerPage({
|
||||
product_name: '伊调研',
|
||||
platform_type: 'PC'
|
||||
});
|
||||
// 提供全局注入的 sensors 实例
|
||||
app.provide('sensors', sensors);
|
||||
// 注册到window中
|
||||
(globalThis as any).sa = sensors;
|
||||
|
||||
// 注册 saTrack 自定义指令
|
||||
registerDirective(app);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册 saTrack 指令,用于点击埋点
|
||||
* @param {App} app - Vue 应用实例
|
||||
*/
|
||||
function registerDirective(app: App) {
|
||||
function bindTrackListener(binding: any) {
|
||||
return () => {
|
||||
const { value: properties } = binding;
|
||||
|
||||
sensorsTrack(properties);
|
||||
};
|
||||
}
|
||||
|
||||
app.directive('sensorsTrack', {
|
||||
mounted(el, binding) {
|
||||
el.addEventListener('click', bindTrackListener(binding));
|
||||
},
|
||||
unmounted(el, binding) {
|
||||
// 清除绑定的事件
|
||||
el.removeEventListener('click', bindTrackListener(binding));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sensorsTrack(properties: any) {
|
||||
sensors.track('YiliResearch_PageClick', properties);
|
||||
}
|
||||
export { sensors, sensorsTrack };
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { fetchBanners } from '@/hooks/request/banner';
|
||||
import { computed, inject } from 'vue';
|
||||
import { sensorsTrack } from '@/utils/plugins/sa';
|
||||
import { computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
@@ -11,8 +12,6 @@ const bannerInfo = computed(() => {
|
||||
});
|
||||
// 当前是否处于分享页面
|
||||
const hasShare = defineModel<boolean>('hasShare', { default: false });
|
||||
// 上层注入的神策对象
|
||||
const sensors = inject<any>('sensors');
|
||||
|
||||
function handleButtonClick() {
|
||||
saTrack(bannerInfo.value);
|
||||
@@ -24,16 +23,11 @@ function handleButtonClick() {
|
||||
}
|
||||
|
||||
function saTrack(record: any) {
|
||||
const config = {
|
||||
eventName: 'ClickBanner',
|
||||
properties: {
|
||||
page: '落地页',
|
||||
module: 'ad',
|
||||
position: 'banner点击_' + record.code,
|
||||
clickTime: new Date().toLocaleString().toString()
|
||||
}
|
||||
};
|
||||
sensors.track(config.eventName, config.properties);
|
||||
sensorsTrack({
|
||||
page_name: 'APP落地页',
|
||||
model_name: record?.code || '',
|
||||
button_name: '立即体验'
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 在挂载之后重新修改 html title 内容
|
||||
@@ -55,13 +49,13 @@ setTimeout(() => {
|
||||
<!-- banner内容 -->
|
||||
<article>
|
||||
<!-- 根据banner的类型使用不同的方式渲染 -->
|
||||
<section class="banner-text" v-if="bannerInfo?.type === 0">
|
||||
<section v-if="bannerInfo?.type === 0" class="banner-text">
|
||||
<p>{{ bannerInfo.synopsis }}</p>
|
||||
</section>
|
||||
<div class="banner-image" v-else-if="bannerInfo?.type === 1">
|
||||
<div v-else-if="bannerInfo?.type === 1" class="banner-image">
|
||||
<el-image fit="cover" loading="lazy" :src="bannerInfo.file_address" />
|
||||
</div>
|
||||
<section class="banner-video" v-else-if="bannerInfo?.type === 2">
|
||||
<section v-else-if="bannerInfo?.type === 2" class="banner-video">
|
||||
<video width="100%" height="auto" controls>
|
||||
<source :src="bannerInfo.file_address" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import { useRouter } from 'vue-router';
|
||||
import { bannerInfo } from '@/views/AD/hooks/useAD';
|
||||
import { fetchBanners } from '@/hooks/request/banner';
|
||||
import { computed, inject } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { sensorsTrack } from '@/utils/plugins/sa';
|
||||
|
||||
const { banners } = fetchBanners();
|
||||
|
||||
@@ -10,15 +11,13 @@ const router = useRouter();
|
||||
// const defineBanners = defineModel('banners');
|
||||
// 如果定义了 banner , 那么 banners 就不再初始化
|
||||
// defineBanners.value && updateBanners(defineBanners.value);
|
||||
const borderRadius = defineModel('borderRadius');
|
||||
const borderRadius = defineModel<number>('borderRadius');
|
||||
// 是否启用平铺展示
|
||||
const stack = defineModel<boolean>('stack', { default: true });
|
||||
// 上级传递的 banners
|
||||
const bannersList = defineModel<any[]>('banners');
|
||||
// 是否存在显示显示数量
|
||||
const limit = defineModel<number>('limit');
|
||||
// 上层注入的神策对象
|
||||
const sensors = inject<any>('sensors');
|
||||
|
||||
function handleBannerClick(banner: any) {
|
||||
// 把对应的信息给 AD 的 hooks
|
||||
@@ -29,17 +28,11 @@ function handleBannerClick(banner: any) {
|
||||
}
|
||||
|
||||
function saTrack(record: any) {
|
||||
const config = {
|
||||
eventName: 'ClickBanner',
|
||||
properties: {
|
||||
page: '首页',
|
||||
module: 'Banner',
|
||||
position: 'Banner点击',
|
||||
imgID: record.code,
|
||||
clickTime: new Date().toLocaleString().toString()
|
||||
}
|
||||
};
|
||||
sensors.track(config.eventName, config.properties);
|
||||
sensorsTrack({
|
||||
page_name: 'APP首页',
|
||||
model_name: record?.code || '',
|
||||
button_name: '轮播图'
|
||||
});
|
||||
}
|
||||
|
||||
const currentBanners = computed(() => {
|
||||
@@ -52,7 +45,7 @@ const currentBanners = computed(() => {
|
||||
|
||||
<template>
|
||||
<div class="slider-container">
|
||||
<van-swipe :autoplay="5000" indicator-color="white" v-if="stack">
|
||||
<van-swipe v-if="stack" :autoplay="5000" indicator-color="white">
|
||||
<van-swipe-item v-for="banner in currentBanners" :key="banner.code">
|
||||
<el-image
|
||||
class="img"
|
||||
|
||||
Reference in New Issue
Block a user