├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .github
└── FUNDING.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.en.md
├── README.md
├── demo
├── css
│ └── style.css
├── js
│ ├── main-for-vue2.js
│ ├── main-for-vue3.js
│ └── routes.js
├── vue2.html
└── vue3.html
├── dist
├── main.d.ts
├── modules
│ ├── cnzz.d.ts
│ ├── getVueVersion.d.ts
│ └── pushCNZZ.d.ts
├── types.d.ts
├── vue-cnzz-analytics.js
├── vue-cnzz-analytics.js.map
├── vue-cnzz-analytics.min.js
└── vue-cnzz-analytics.min.js.map
├── package.json
├── rollup.config.ts
├── scripts
└── verifyCommit.js
├── src
├── global.d.ts
├── main.ts
├── modules
│ ├── cnzz.ts
│ ├── getVueVersion.ts
│ └── pushCNZZ.ts
└── types.ts
├── tsconfig.json
├── vue-cnzz-analytics.d.ts
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false,
7 | "targets": {
8 | "browsers": "> 1%, IE 11, not op_mini all, not dead"
9 | },
10 | "useBuiltIns": "usage",
11 | "corejs": 2
12 | }
13 | ]
14 | ],
15 | "plugins": [
16 | "@babel/plugin-proposal-class-properties"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | max_line_length = 80
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | max_line_length = 0
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | demo/*
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | browser: true,
6 | },
7 | extends: ['eslint:recommended', 'prettier'],
8 | parser: '@typescript-eslint/parser',
9 | parserOptions: {
10 | ecmaVersion: 2020,
11 | },
12 | plugins: ['@typescript-eslint', 'prettier'],
13 | rules: {
14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
16 | 'prettier/prettier': 'warn',
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: https://github.com/chengpeiquan/sponsor
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 chengpeiquan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | This package is no longer maintained, please use [@web-analytics/vue](https://analytics.js.org/vue/) , which has an easier method of use while maintaining the original functions.
2 |
3 | ---
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | [简体中文](https://github.com/analyticsjs/vue-cnzz-analytics/blob/master/README.md) | English
18 |
19 | Only 3 kB, this plugin base on the CNZZ analytics, it can help you quickly to collect the page views on your website, including single page web application.
20 |
21 | >Since the version v2.0.0, it supports the Vue 3.0, and is compatible with the Vue 2.0, you can see the live demo to learn more.
If you haven’t started using Vue 3.0, welcome to read the tutorial [learning Vue3](https://vue3.chengpeiquan.com/) .
22 |
23 | ## Features
24 |
25 | * Asynchronously load the CNZZ analytics scripts, no need to modify the entry HTML.
26 |
27 | * Support the deployment of multiple site IDs and corresponding data reporting.
28 |
29 | * Supports automatic reporting of PV data generated by route switching (This feature need [Vue Router](https://router.vuejs.org/), It can support hash mode and history mode).
30 |
31 | * Support manual submission of page views reports.
32 |
33 | * Support manual submission of event reports.
34 |
35 | * Since the version v2.0.0, the plugin can automatically recognize the Vue version at Vue 2.0 or Vue 3.0 .
36 |
37 | * Since the version v2.1.0, Hooks API is provided (So the usage of CDN installation is slightly adjusted)
38 |
39 | ## Project
40 |
41 | As long as Vue and Vue Router are introduced, the projects can be used normally, no matter what method is used to develop your project, e.g. :
42 |
43 | * Vue-CLI scaffolding project
44 |
45 | * Vite project
46 |
47 | * Introduce the HTML page of Vue related CDN
48 |
49 | * VuePress project
50 |
51 | It is not limited to SPA single page projects, it can also be used in SSG / SSR projects.
52 |
53 | ## Preview
54 |
55 | Both live demos have enabled debug mode, and you can open the console to view the report.
56 |
57 | Vue 2.0 :[vue-cnzz-analytics demo for Vue 2.x](https://analyticsjs.github.io/vue-cnzz-analytics/demo/vue2.html "vue-cnzz-analytics demo for Vue 2.x")
58 |
59 | Vue 3.0 :[vue-cnzz-analytics demo for Vue 3.x](https://analyticsjs.github.io/vue-cnzz-analytics/demo/vue3.html "vue-cnzz-analytics demo for Vue 3.x")
60 |
61 | ## Options
62 |
63 | Option|Required|Type|Description
64 | :-:|:-:|:-:|-
65 | router|false|object|Vue Router(It is optional since v2.2.0.)
66 | siteIdList|true|number[]|The site ids for CNZZ analytics, if only one site needs to be reported, just keep one item in the array.
67 | isDebug|false|boolean|if `true`, it will open the debug mode,you can see the log in the console.
68 |
69 | Tips: Please remember to turn off the debug mode before publish.
70 |
71 | ## Install
72 |
73 | You can install the plugin from NPM.
74 |
75 | ```bash
76 | npm install vue-cnzz-analytics --save-dev
77 | ```
78 |
79 | Can also use the CDN URL in your HTML.
80 |
81 | ```html
82 |
83 | ```
84 |
85 | ## Usage
86 |
87 | If use NPM, you must import the plugin in `main.js` .
88 |
89 | ```js
90 | import cnzzAnalytics from 'vue-cnzz-analytics'
91 | ```
92 |
93 | Then, refer to the sample code in Vue 2.0 and Vue 3.0 below to use it.
94 |
95 | When the route is switched, the new URL address will be reported to CNZZ analytics after the visit.
96 |
97 | ### Use in the Vue 2.0
98 |
99 | See:[main.js - Vue 2.0 demo](https://analyticsjs.github.io/vue-cnzz-analytics/demo/js/main-for-vue2.js)
100 |
101 | >Since the version v2.1.0, if you use CDN in your HTML, must be use `cnzzAnalytics.default` to use the plugin.
102 |
103 | ```js
104 | Vue.use(cnzzAnalytics, {
105 | router: router,
106 | siteIdList: [
107 | 11111,
108 | 22222
109 | ],
110 | isDebug: false
111 | });
112 | ```
113 |
114 | ### Use in the Vue 3.0
115 |
116 | See:[main.js - Vue 3.0 demo](https://analyticsjs.github.io/vue-cnzz-analytics/demo/js/main-for-vue3.js)
117 |
118 | >Since the version v2.1.0, if you use CDN in your HTML, must be use `cnzzAnalytics.default` to use the plugin.
119 |
120 | ```js
121 | createApp(app)
122 | .use(router)
123 | .use(cnzzAnalytics, {
124 | router: router,
125 | siteIdList: [
126 | 11111,
127 | 22222
128 | ],
129 | isDebug: false
130 | })
131 | .mount('#app');
132 | ```
133 |
134 | ### Use in the VuePress
135 |
136 | The plugin can also be used in [VuePress](https://vuepress.vuejs.org/zh/) project.
137 |
138 | In the `/docs/.vuepress` folder under the project, create a file named `enhanceApp.js`, and write the following code in this file.
139 |
140 | You can see [App Level Enhancements - VuePress](https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements) to learn more.
141 |
142 | ```js
143 | import cnzzAnalytics from 'vue-cnzz-analytics'
144 |
145 | export default ({ Vue, router }) => {
146 | Vue.use(cnzzAnalytics, {
147 | router: router,
148 | siteIdList: [
149 | 11111,
150 | 22222
151 | ],
152 | isDebug: false
153 | });
154 | };
155 | ```
156 |
157 | You can turn on the debug mode in the development environment to learn about related reports (remember to turn off debug before going online).
158 |
159 | ## API
160 |
161 | Since the version v2.1.0, you can use the Global API `$pushCNZZ` and the Hooks API `usePush` in your project, they both support the Vue 2.0 and 3.0.
162 |
163 | >The APIs can't be used directly, it needs to cooperate with the [Methods](#Methods) to operate the specific functions.
164 |
165 | ### The Global API
166 |
167 | In the Vue 2.0:
168 |
169 | ```js
170 | // xxx.vue in Vue 2.0
171 | export default {
172 | // ...
173 | mounted () {
174 | this.$pushCNZZ.pv('/example-url/');
175 | },
176 | // ...
177 | }
178 | ```
179 |
180 | In the Vue 3.0, you can use the Global Properties:
181 |
182 | ```js
183 | // xxx.vue in Vue 3.0
184 | import { getCurrentInstance } from 'vue'
185 |
186 | export default {
187 | setup () {
188 | const app = getCurrentInstance();
189 | app.appContext.config.globalProperties.$pushCNZZ.pv('/example-url/');
190 | }
191 | }
192 | ```
193 |
194 | You can also import the proxy component in the current instance to operate:
195 |
196 | ```js
197 | // xxx.vue in Vue 3.0
198 | import { getCurrentInstance } from 'vue'
199 |
200 | export default {
201 | setup () {
202 | const { proxy } = getCurrentInstance();
203 | proxy.$pushCNZZ.pv('/example-url/');
204 | }
205 | }
206 | ```
207 |
208 | ### The Hooks API
209 |
210 | In the Vue 2.0:
211 |
212 | ```js
213 | // xxx.vue in Vue 2.0
214 | import { usePush } from 'vue-cnzz-analytics'
215 |
216 | export default {
217 | // ...
218 | data () {
219 | return {
220 | cnzz: usePush()
221 | }
222 | },
223 | mounted () {
224 | this.cnzz.pv('/example-url/');
225 | },
226 | // ...
227 | }
228 | ```
229 |
230 | In the Vue 3.0, just use it as if you were using the route `const router = useRouter();`.
231 |
232 | ```js
233 | // xxx.vue in Vue 3.0
234 | import { usePush } from 'vue-cnzz-analytics'
235 |
236 | export default {
237 | setup () {
238 | const cnzz = usePush();
239 | cnzz.pv('/example-url/');
240 | }
241 | }
242 | ```
243 |
244 | If the name of the hook API has already been declared, you can rename it when import.
245 |
246 | ```js
247 | import { usePush as useCnzz } from 'vue-cnzz-analytics'
248 | const cnzz = useCnzz();
249 | ```
250 |
251 | ## Methods
252 |
253 | All methods are needs to be triggered through the API, and the methods supported by the Global API and the Hooks API are exactly the same.
254 |
255 | Method|Description
256 | :--|:--
257 | Manually report the page views|[Click here to see.](#manually-report-the-page-views)
258 | Manually report the event analysis|[Click here to see.](#manually-report-the-event-analysis)
259 |
260 | >Since there are still many users of Vue 2.0, the following examples only use the operation method of Vue 2.0 to demonstrate. Vue 3.0 can call specific methods according to the description of the Hooks API.
261 |
262 | Tips: If multiple site IDs are configured, the data will be reported to all sites at the same time.
263 |
264 | ### Manually report the page views
265 |
266 | If you switch content rendering on some pages through Tab, but you need to report access data, you can use this method to manually report.
267 |
268 | Method|Description
269 | :-:|-
270 | pv|Manually perform PV data reporting.
271 |
272 | **Params**
273 |
274 | Param|Required|Type|Description
275 | :-:|:-:|:-:|-
276 | pageUrl|false|string|The URL submitted for the report must be a relative path starting with `/`, if not filled, it will be submitted as the domain name root directory by default.
277 | fromUrl|false|string|The URL of the incoming page must be an absolute address beginning with `http` or `https`, if it is not filled in, the statistics platform will consider the source of the visit to be a direct input address.
278 |
279 | **Example**
280 |
281 | ```js
282 | this.$pushCNZZ.pv('/example-url/', 'https://example.com/example-from-url/');
283 | ```
284 |
285 | ### Manually report the event analysis
286 |
287 | For example, there is a "exchange" function button on your page. If you want to count the clicks of this button, you can perform click analysis by binding the button to report events.
288 |
289 | Method|Description
290 | :-:|-
291 | event|Manually perform event analysis data reporting.
292 |
293 | **Params**
294 |
295 | Param|Required|Type|Description
296 | :-:|:-:|:-:|-
297 | category|true|string|The name of the location where the event occurred, e.g. `banner`
298 | action|true|string|The description of the behavior that generated the event, e.g. `click`
299 | label|false|string|The name of the label that generated the event can be used to record the event sub-id, e.g. `bannerId_123`. (@default: '')
300 | value|false|number|The score of the event. (@default: 0)
301 | nodeId|false|string|The id of the element that generated the event. (@default: '')
302 |
303 | **Example**
304 |
305 | ```js
306 | this.$pushCNZZ.event(
307 | this.category,
308 | this.action,
309 | this.label,
310 | this.value,
311 | this.nodeId
312 | );
313 | ```
314 |
315 | ## CHANGELOG
316 |
317 | See:[releases](https://github.com/analyticsjs/vue-cnzz-analytics/releases)
318 |
319 | ## License
320 |
321 | [MIT License](https://github.com/analyticsjs/vue-cnzz-analytics/blob/master/LICENSE) © 2019 [chengpeiquan](https://github.com/chengpeiquan)
322 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 本包不再维护,请使用 [@web-analytics/vue](https://analytics.js.org/vue/) ,在保持原有功能的基础上,具有更简单的使用方法。
2 |
3 | ---
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 简体中文 | [English](https://github.com/analyticsjs/vue-cnzz-analytics/blob/master/README.en.md)
18 |
19 | 一个只有 3 kB 大小的插件,可以帮你轻松解决 SPA 单页面项目浏览数据不准确的问题,基于 Vue 路由访问轨迹自动向友盟统计平台上报 PV / 事件数据。
20 |
21 | >本插件自 v2.0.0 开始,最新版插件支持在 Vue 3.0 项目下使用,同时兼容 Vue 2.0 项目的使用,具体使用方法请看下方说明以及在线 demo 。
对 Vue 3.0 感兴趣,但还在观望的同学,欢迎阅读我踩坑总结的:[Vue3.0学习教程与实战案例](https://vue3.chengpeiquan.com/) (持续更新ing)
22 |
23 | ## 功能
24 |
25 | * 异步载入友盟统计脚本,无需修改入口 HTML
26 |
27 | * 支持部署多个站点 ID ,并对应进行数据上报(跨部门合作项目,双方均要收集数据时非常有用)
28 |
29 | * 支持自动上报路由切换产生的 PV 数据(需引入 [Vue Router](https://router.vuejs.org/),支持 hash 模式和 history 模式的地址)
30 |
31 | * 支持手动提交 PV 上报
32 |
33 | * 支持手动提交事件分析上报
34 |
35 | * 自动识别 Vue 版本,自动适配 Vue 2.0 / Vue 3.0 使用(本插件 v2.0.0 版本新增)
36 |
37 | * 提供了 Hooks API(本插件 v2.1.0 版本新增,因此 CDN 安装的用法略有调整,请留意使用说明)
38 |
39 | ## 项目
40 |
41 | 理论上只要引入了 Vue (必须) 和 Vue Router (自 v2.2.0 起是可选) 的项目均可以正常使用,包括但不限于以下类型:
42 |
43 | * Vue-CLI 脚手架项目
44 |
45 | * Vite 项目
46 |
47 | * 引入 Vue 相关 CDN 的 HTML 页面
48 |
49 | * VuePress 项目
50 |
51 | 也不仅限于 SPA 单页面项目,在 SSG / SSR 项目里也可以使用。
52 |
53 | ## 预览
54 |
55 | 两个在线 demo 均已开启 debug 模式,可开启控制台查看上报情况。
56 |
57 | Vue 2.0 版本:[vue-cnzz-analytics demo for Vue 2.x](https://analyticsjs.github.io/vue-cnzz-analytics/demo/vue2.html "vue-cnzz-analytics demo for Vue 2.x")
58 |
59 | Vue 3.0 版本:[vue-cnzz-analytics demo for Vue 3.x](https://analyticsjs.github.io/vue-cnzz-analytics/demo/vue3.html "vue-cnzz-analytics demo for Vue 3.x")
60 |
61 | ## 选项
62 |
63 | 选项|是否必填|选项类型|选项说明
64 | :-:|:-:|:-:|-
65 | router|否|object|Vue Router(自 v2.2.0 版本开始为可选,无路由的单页则不必传该选项)
66 | siteIdList|是|number[]|友盟统计的站点 id 列表,只有一个站点需要上报就保留一个 id 即可
67 | isDebug|否|boolean|是否开启 debug 模式,默认 `false`,开启后会在 F12 控制台打印上报信息
68 |
69 | 友情提示:上线前记得关闭 debug 模式。
70 |
71 | ## 安装
72 |
73 | 方式一:通过 NPM 安装
74 |
75 | ```bash
76 | npm install vue-cnzz-analytics --save-dev
77 | ```
78 |
79 | 方式二:通过 CDN 安装
80 |
81 | ```html
82 |
83 | ```
84 |
85 | ## 启用
86 |
87 | 通过 NPM 安装的项目,需要先在 main.js 里引入插件(通过 CDN 则无需该步骤)。
88 |
89 | ```js
90 | import cnzzAnalytics from 'vue-cnzz-analytics'
91 | ```
92 |
93 | 安装插件后,在 main.js 引入以下代码(注意 Vue 2.0 和 Vue 3.0 的用法区别),即可开启自动上报功能,首次访问页面会部署统计代码并提交第一次访问数据上报。
94 |
95 | 后续在路由切换过程中,也会根据路由的切换提交相应的 URL 信息到友盟统计。
96 |
97 | ### 在 Vue 2.0 里使用
98 |
99 | 可参考demo:[main.js - Vue 2.0 demo](https://analyticsjs.github.io/vue-cnzz-analytics/demo/js/main-for-vue2.js)
100 |
101 | >自 v2.1.0 版本开始,如果是通过 CDN 安装,需要使用 `cnzzAnalytics.default` 去激活插件,通过 NPM 安装的脚手架项目则使用 `cnzzAnalytics` 就可以
102 |
103 | ```js
104 | // 启动插件
105 | Vue.use(cnzzAnalytics, {
106 | router: router,
107 | siteIdList: [
108 | 11111,
109 | 22222
110 | ],
111 | isDebug: false
112 | });
113 | ```
114 |
115 | ### 在 Vue 3.0 里使用
116 |
117 | 可参考demo:[main.js - Vue 3.0 demo](https://analyticsjs.github.io/vue-cnzz-analytics/demo/js/main-for-vue3.js)
118 |
119 | >自 v2.1.0 版本开始,如果是通过 CDN 安装,需要使用 `cnzzAnalytics.default` 去激活插件,通过 NPM 安装的脚手架项目则使用 `cnzzAnalytics` 就可以
120 |
121 | ```js
122 | /**
123 | * 初始化Vue
124 | */
125 | createApp(app)
126 | // 启动路由
127 | .use(router)
128 |
129 | // 启动插件
130 | .use(cnzzAnalytics, {
131 | router: router,
132 | siteIdList: [
133 | 11111,
134 | 22222
135 | ],
136 | isDebug: false
137 | })
138 |
139 | // 挂载到节点上
140 | .mount('#app');
141 | ```
142 |
143 | ### 在 VuePress 里使用
144 |
145 | 插件也支持在Vue的静态文档 [VuePress](https://vuepress.vuejs.org/zh/) 项目里使用。
146 |
147 | 在项目下的 `/docs/.vuepress` 文件夹下,创建一个 `enhanceApp.js`,按照下面的方式引入即可启动数据上报功能。
148 |
149 | 官方文档传送门:[应用级别的配置 - VuePress](https://vuepress.vuejs.org/zh/guide/basic-config.html#%E5%BA%94%E7%94%A8%E7%BA%A7%E5%88%AB%E7%9A%84%E9%85%8D%E7%BD%AE)
150 |
151 | ```js
152 | import cnzzAnalytics from 'vue-cnzz-analytics'
153 |
154 | export default ({ Vue, router }) => {
155 | Vue.use(cnzzAnalytics, {
156 | router: router,
157 | siteIdList: [
158 | 11111,
159 | 22222
160 | ],
161 | isDebug: false
162 | });
163 | };
164 | ```
165 |
166 | 可在开发环境打开 debug 模式了解相关的上报情况(上线前记得关闭 debug )。
167 |
168 | ## API
169 |
170 | 自 v2.1.0 版本开始,插件支持直接调用的全局 API `$pushCNZZ` 和按需导入的钩子 API `usePush` 两种方式。
171 |
172 | 这两种方式在 Vue 2.0 和 3.0 里均可以使用,只不过按照使用习惯和从 Vue 官方推荐的角度来说,全局 API 更适合 Vue 2.0 项目,钩子 API 更适合 Vue 3.0 项目。
173 |
174 | > 插件的 API 不可以直接使用,需要配合 API 里面的 [方法](#方法) 才可以操作到具体功能。
175 |
176 | ### 全局 API
177 |
178 | 在 Vue 2.0 里,只需要通过我们熟悉的 `this` 去操作即可:
179 |
180 | ```js
181 | // xxx.vue in Vue 2.0
182 | export default {
183 | // ...
184 | mounted () {
185 | this.$pushCNZZ.pv('/example-url/');
186 | },
187 | // ...
188 | }
189 | ```
190 |
191 | 在 Vue 3.0 里,可以按照官方文档的推荐,导入当前实例变量,通过当前实例变量去操作全局方法:
192 |
193 | ```js
194 | // xxx.vue in Vue 3.0
195 | import { getCurrentInstance } from 'vue'
196 |
197 | export default {
198 | setup () {
199 | const app = getCurrentInstance();
200 | app.appContext.config.globalProperties.$pushCNZZ.pv('/example-url/');
201 | }
202 | }
203 | ```
204 |
205 | 也可以导入当前实例里的代理组件去操作:
206 |
207 | ```js
208 | // xxx.vue in Vue 3.0
209 | import { getCurrentInstance } from 'vue'
210 |
211 | export default {
212 | setup () {
213 | const { proxy } = getCurrentInstance();
214 | proxy.$pushCNZZ.pv('/example-url/');
215 | }
216 | }
217 | ```
218 |
219 | ### 钩子 API
220 |
221 | >钩子 API 需要在用到的组件里 import 导入才可以使用。
222 |
223 | 在 Vue 2.0 里,你可以绑定一个钩子变量去使用:
224 |
225 | ```js
226 | // xxx.vue in Vue 2.0
227 | import { usePush } from 'vue-cnzz-analytics'
228 |
229 | export default {
230 | // ...
231 | data () {
232 | return {
233 | // 创建钩子变量
234 | cnzz: usePush()
235 | }
236 | },
237 | mounted () {
238 | // 通过钩子变量去触发方法
239 | this.cnzz.pv('/example-url/');
240 | },
241 | // ...
242 | }
243 | ```
244 |
245 | 在 Vue 3.0 里,就像在使用路由 `const router = useRouter();` 一样去使用就可以。
246 |
247 | ```js
248 | // xxx.vue in Vue 3.0
249 | import { usePush } from 'vue-cnzz-analytics'
250 |
251 | export default {
252 | setup () {
253 | // 创建钩子变量
254 | const cnzz = usePush();
255 |
256 | // 通过钩子变量去触发方法
257 | cnzz.pv('/example-url/');
258 | }
259 | }
260 | ```
261 |
262 | 另外,如果 API 与其他插件冲突的话(比如你同时使用了 [vue-baidu-analytics](https://github.com/analyticsjs/vue-baidu-analytics)),你可以在导入的时候重命名:
263 |
264 | ```js
265 | import { usePush as useCnzz } from 'vue-cnzz-analytics'
266 | const cnzz = useCnzz();
267 | ```
268 |
269 | ## 方法
270 |
271 | 方法需要通过 API 去触发,全局 API 和 钩子 API 支持的方法都是完全一样的。
272 |
273 | 方法功能|使用说明
274 | :--|:--
275 | 手动上报页面 PV|[点击查看](#手动上报页面PV)
276 | 手动上报事件分析|[点击查看](#手动上报事件分析)
277 |
278 | > 由于目前 Vue 2.0 的使用者还比较多,下面的举例均只用 Vue 2.0 的操作方法进行演示,Vue 3.0 可根据钩子 API 的说明去调用具体的方法。
279 |
280 | 注:如果配置了多个站点 ID ,数据都会同时上报给所有站点。
281 |
282 | ### 手动上报页面 PV
283 |
284 | 如果你有些页面是通过 Tab 切页进行内容渲染切换,但又需要上报访问数据的话,就可以使用这个方法来进行手动上报。
285 |
286 | 方法名称|功能说明
287 | :-:|-
288 | pv|手动执行 PV 数据上报
289 |
290 | **参数**
291 |
292 | 参数|是否必填|参数类型|参数说明
293 | :-:|:-:|:-:|-
294 | pageUrl|否|string|提交上报的 URL ,必须是以 `/` 开头的相对路径,如果不填,则会默认提交为域名根目录
295 | fromUrl|否|string|来路页面的url,必须是以 `http` 或 `https` 开头的绝对地址,如果不填,则统计平台会认为访问来源为直接输入地址
296 |
297 | **使用示范**
298 |
299 | ```js
300 | this.$pushCNZZ.pv('/example-url/', 'https://example.com/example-from-url/');
301 | ```
302 |
303 | ### 手动上报事件分析
304 |
305 | 比如你的页面上有个 “换一换” 的功能按钮,想要统计这个按钮的点击情况,就可以通过给按钮绑定上报事件来进行点击情况分析。
306 |
307 | 方法名称|功能说明
308 | :-:|-
309 | event|手动执行事件分析数据上报
310 |
311 | **参数**
312 |
313 | 参数|是否必填|参数类型|参数说明
314 | :-:|:-:|:-:|-
315 | category|是|string|产生该事件的位置名称,比如 `首页banner`
316 | action|是|string|产生该事件的行为描述,比如 `点击`
317 | label|否|string|产生该事件的标签名称,可以用来记录事件子 id,比如 `bannerId_123`,默认为空
318 | value|否|number|该事件的分值,默认 0
319 | nodeId|否|string|产生该事件的元素id,默认为空
320 |
321 | **使用示范**
322 |
323 | ```js
324 | this.$pushCNZZ.event(
325 | this.category,
326 | this.action,
327 | this.label,
328 | this.value,
329 | this.nodeId
330 | );
331 | ```
332 |
333 | ## 更新记录
334 |
335 | 点击查看:[releases](https://github.com/analyticsjs/vue-cnzz-analytics/releases)
336 |
337 | ## License
338 |
339 | [MIT License](https://github.com/analyticsjs/vue-cnzz-analytics/blob/master/LICENSE) © 2020 [chengpeiquan](https://github.com/chengpeiquan)
340 |
--------------------------------------------------------------------------------
/demo/css/style.css:
--------------------------------------------------------------------------------
1 | #app,
2 | .section {
3 | display: flex;
4 | flex-direction: column;
5 | justify-content: flex-start;
6 | align-items: center;
7 | }
8 | .section {
9 | margin-bottom: 40px;
10 | }
11 | .title {
12 | font-size: 40px;
13 | color: #000;
14 | }
15 | .link {
16 | color: #666;
17 | text-decoration: none;
18 | }
19 | .link:hover {
20 | color: #000;
21 | }
22 | .nav {
23 | margin-bottom: 20px;
24 | }
25 | .nav .item {
26 | color: #666;
27 | margin: 0 10px 20px;
28 | }
29 | .nav .cur {
30 | color: #000;
31 | font-weight: bold;
32 | }
33 | .label {
34 | display: flex;
35 | justify-content: center;
36 | align-items: center;
37 | margin-bottom: 20px;
38 | }
39 | .text {
40 | display: flex;
41 | justify-content: flex-end;
42 | align-items: center;
43 | width: 60px;
44 | font-size: 14px;
45 | color: #333;
46 | margin-right: 20px;
47 | }
48 | .input {
49 | display: flex;
50 | align-items: center;
51 | width: 240px;
52 | height: 40px;
53 | font-size: 14px;
54 | box-sizing: border-box;
55 | padding: 0 10px;
56 | }
57 | .button {
58 | padding: 5px 20px;
59 | cursor: pointer;
60 | }
--------------------------------------------------------------------------------
/demo/js/main-for-vue2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 初始化路由
3 | * routes是来自 js/routes.js 里面的配置
4 | */
5 | const router = new VueRouter({
6 | routes,
7 | linkActiveClass: 'cur',
8 | linkExactActiveClass: 'cur'
9 | });
10 |
11 |
12 | /**
13 | * 引入统计插件
14 | * @description 自 v2.1.0 版本开始,需要使用 .default 去激活插件
15 | */
16 | Vue.use(cnzzAnalytics.default, {
17 | router: router,
18 | siteIdList: [
19 | 11111,
20 | 22222
21 | ],
22 | isDebug: true
23 | });
24 |
25 |
26 | /**
27 | * 初始化Vue
28 | */
29 | const app = new Vue({
30 | el: '#app',
31 | router,
32 | data () {
33 | return {
34 | pageUrl: '',
35 | fromUrl: '',
36 | category: '',
37 | action: '',
38 | label: '',
39 | value: '',
40 | nodeId: '',
41 |
42 | // 也可以绑定一个钩子变量去使用
43 | cnzz: cnzzAnalytics.usePush()
44 | }
45 | },
46 | mounted () {
47 | this.cnzz.pv('/use-push-api/?from=mounted');
48 | },
49 | methods: {
50 | /**
51 | * 提交 pv
52 | * @description 支持两种推送方式
53 | */
54 | pv () {
55 | // 使用默认全局 API
56 | this.$pushCNZZ.pv(
57 | this.pageUrl,
58 | this.fromUrl
59 | );
60 |
61 | // 使用钩子 API
62 | // this.cnzz.pv(
63 | // this.pageUrl,
64 | // this.fromUrl
65 | // );
66 | },
67 |
68 | /**
69 | * 提交事件
70 | * @description 支持两种推送方式
71 | */
72 | event () {
73 | // 使用默认全局 API
74 | // this.$pushCNZZ.event(
75 | // this.category,
76 | // this.action,
77 | // this.label,
78 | // this.value,
79 | // this.nodeId
80 | // );
81 |
82 | // 使用钩子 API
83 | this.cnzz.event(
84 | this.category,
85 | this.action,
86 | this.label,
87 | this.value,
88 | this.nodeId
89 | );
90 | }
91 | }
92 | });
93 |
--------------------------------------------------------------------------------
/demo/js/main-for-vue3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 导入需要用到的组件
3 | */
4 | const { createRouter, createWebHashHistory } = VueRouter;
5 | const { createApp, getCurrentInstance, ref } = Vue;
6 | const { usePush } = cnzzAnalytics;
7 |
8 |
9 | /**
10 | * 初始化路由
11 | * routes是来自 js/routes.js 里面的配置
12 | */
13 | const router = createRouter({
14 | history: createWebHashHistory(),
15 | routes,
16 | linkActiveClass: 'cur',
17 | linkExactActiveClass: 'cur'
18 | });
19 |
20 |
21 | /**
22 | * 创建实例
23 | */
24 | const app = {
25 | setup () {
26 | /**
27 | * 新的推荐方式
28 | * @description 创建一个钩子变量去使用,更适合于 TypeScript 项目
29 | */
30 | const cnzz = usePush();
31 |
32 | /**
33 | * 原来的方式
34 | * @description 从当前实例里,导入代理组件去操作,对 TS 项目不够友好
35 | */
36 | // const instance = getCurrentInstance();
37 | // const { proxy } = instance;
38 |
39 |
40 | // 初始化要用到的数据
41 | const pageUrl = ref('');
42 | const fromUrl = ref('');
43 | const category = ref('');
44 | const action = ref('');
45 | const label = ref('');
46 | const value = ref('');
47 | const nodeId = ref('');
48 |
49 | /**
50 | * 提交 pv
51 | * @description 支持两种推送方式
52 | */
53 | const pv = () => {
54 | // 通过钩子去操作
55 | cnzz.pv(
56 | pageUrl.value,
57 | fromUrl.value
58 | );
59 |
60 | // 也可以通过全局属性去操作
61 | // instance.appContext.config.globalProperties.$pushCNZZ.pv(
62 | // pageUrl.value,
63 | // fromUrl.value
64 | // );
65 |
66 | // 也可以通过代理组件去操作
67 | // proxy.$pushCNZZ.pv(
68 | // pageUrl.value,
69 | // fromUrl.value
70 | // );
71 | }
72 |
73 | // 提交事件的操作
74 | const event = () => {
75 | // 通过钩子去操作
76 | cnzz.event(
77 | category.value,
78 | action.value,
79 | label.value,
80 | value.value,
81 | nodeId.value
82 | );
83 |
84 | // 也可以通过全局属性去操作
85 | // instance.appContext.config.globalProperties.$pushCNZZ.event(
86 | // category.value,
87 | // action.value,
88 | // label.value,
89 | // value.value,
90 | // nodeId.value
91 | // );
92 |
93 | // 也可以通过代理组件去操作
94 | // proxy.$pushCNZZ.event(
95 | // category.value,
96 | // action.value,
97 | // label.value,
98 | // value.value,
99 | // nodeId.value
100 | // );
101 | }
102 |
103 | // Vue 3.0 需要把模板要用到的东西 return 出去
104 | return {
105 | // 数据
106 | pageUrl,
107 | fromUrl,
108 | category,
109 | action,
110 | label,
111 | value,
112 | nodeId,
113 |
114 | // 方法
115 | pv,
116 | event
117 | }
118 | }
119 | };
120 |
121 |
122 | /**
123 | * 初始化Vue
124 | */
125 | createApp(app)
126 | // 启动路由
127 | .use(router)
128 |
129 | // 启动插件
130 | .use(cnzzAnalytics.default, {
131 | router: router,
132 | siteIdList: [
133 | 11111,
134 | 22222
135 | ],
136 | isDebug: true
137 | })
138 |
139 | // 挂载到节点上
140 | .mount('#app');
141 |
--------------------------------------------------------------------------------
/demo/js/routes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 定义路由信息
3 | */
4 | const routes = [
5 | {
6 | path: '/',
7 | redirect: '/page1'
8 | },
9 | {
10 | path: '/page1',
11 | component: {
12 | template: '当前是 Page1 的路由
'
13 | }
14 | },
15 | {
16 | path: '/page2',
17 | component: {
18 | template: '当前是 Page2 的路由
'
19 | }
20 | },
21 | {
22 | path: '/page3',
23 | component: {
24 | template: '当前是 Page3 的路由
'
25 | }
26 | }
27 | ];
--------------------------------------------------------------------------------
/demo/vue2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [Vue2] vue cnzz analytics demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 | 切换路由自动上报测试
22 |
23 | Go to Page1
24 | Go to Page2
25 | Go to Page3
26 |
27 |
28 |
29 |
30 |
42 |
43 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/demo/vue3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [Vue3] vue cnzz analytics demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 | 切换路由自动上报测试
22 |
23 | Go to Page1
24 | Go to Page2
25 | Go to Page3
26 |
27 |
28 |
29 |
30 |
42 |
43 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/dist/main.d.ts:
--------------------------------------------------------------------------------
1 | import type { Options, Vue } from '@/types'
2 | export declare function usePush(): {
3 | pv: (pageUrl: string, fromUrl?: string) => void
4 | event: (
5 | category: string,
6 | action: string,
7 | label: string,
8 | value: number,
9 | nodeId: string
10 | ) => void
11 | }
12 | export default function install(
13 | Vue: Vue,
14 | { router, siteIdList, isDebug }: Partial
15 | ): boolean
16 |
--------------------------------------------------------------------------------
/dist/modules/cnzz.d.ts:
--------------------------------------------------------------------------------
1 | declare class CNZZ {
2 | siteId: number
3 | isDebug: boolean
4 | constructor(siteId?: number, isDebug?: boolean)
5 | init(): void
6 | setAccount(): void
7 | trackPageview(pageUrl: string, fromUrl?: string): void
8 | trackEvent(
9 | category: string,
10 | action: string,
11 | label: string,
12 | value: number,
13 | nodeId: string
14 | ): void
15 | }
16 | export default CNZZ
17 |
--------------------------------------------------------------------------------
/dist/modules/getVueVersion.d.ts:
--------------------------------------------------------------------------------
1 | import type { Vue } from '@/types'
2 | declare const getVueVersion: (Vue: Vue) => number
3 | export default getVueVersion
4 |
--------------------------------------------------------------------------------
/dist/modules/pushCNZZ.d.ts:
--------------------------------------------------------------------------------
1 | declare class PushCNZZ {
2 | siteIdList: number[];
3 | isDebug: boolean;
4 | constructor(siteIdList: number[], isDebug: boolean);
5 | init(): void;
6 | pv(pageUrl: string, fromUrl?: string): void;
7 | event(category: string, action: string, label: string, value: number, nodeId: string): void;
8 | }
9 | export default PushCNZZ;
10 |
--------------------------------------------------------------------------------
/dist/types.d.ts:
--------------------------------------------------------------------------------
1 | import PushCNZZ from '@m/pushCNZZ'
2 | export interface Options {
3 | router: any
4 | siteIdList: number[]
5 | isDebug: boolean
6 | }
7 | export interface Vue {
8 | prototype: any
9 | $pushCNZZ: PushCNZZ
10 | version: number | string
11 | config: any
12 | }
13 |
--------------------------------------------------------------------------------
/dist/vue-cnzz-analytics.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * name: vue-cnzz-analytics
3 | * version: v2.2.0
4 | * author: chengpeiquan
5 | */
6 | ;(function (global, factory) {
7 | typeof exports === 'object' && typeof module !== 'undefined'
8 | ? factory(exports)
9 | : typeof define === 'function' && define.amd
10 | ? define(['exports'], factory)
11 | : ((global =
12 | typeof globalThis !== 'undefined' ? globalThis : global || self),
13 | factory((global.cnzzAnalytics = {})))
14 | })(this, function (exports) {
15 | 'use strict'
16 |
17 | /*! *****************************************************************************
18 | Copyright (c) Microsoft Corporation.
19 |
20 | Permission to use, copy, modify, and/or distribute this software for any
21 | purpose with or without fee is hereby granted.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
24 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
26 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
27 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 | PERFORMANCE OF THIS SOFTWARE.
30 | ***************************************************************************** */
31 | function __spreadArray(to, from, pack) {
32 | if (pack || arguments.length === 2)
33 | for (var i = 0, l = from.length, ar; i < l; i++) {
34 | if (ar || !(i in from)) {
35 | if (!ar) ar = Array.prototype.slice.call(from, 0, i)
36 | ar[i] = from[i]
37 | }
38 | }
39 | return to.concat(ar || from)
40 | }
41 |
42 | var CNZZ = (function () {
43 | function CNZZ(siteId, isDebug) {
44 | if (siteId === void 0) {
45 | siteId = 0
46 | }
47 | if (isDebug === void 0) {
48 | isDebug = false
49 | }
50 | this.siteId = siteId
51 | this.isDebug = isDebug
52 | }
53 | CNZZ.prototype.init = function () {
54 | window._czc = window._czc ? window._czc : []
55 | var SCRIPT = document.createElement('script')
56 | SCRIPT['async'] = true
57 | SCRIPT['src'] =
58 | 'https://s9.cnzz.com/z_stat.php?id=' +
59 | this.siteId +
60 | '&web_id=' +
61 | this.siteId
62 | document.querySelector('head').appendChild(SCRIPT)
63 | if (this.isDebug) {
64 | console.log(
65 | '[vue-cnzz-analytics] siteId load done.\nsiteId: ' + this.siteId
66 | )
67 | }
68 | }
69 | CNZZ.prototype.setAccount = function () {
70 | window._czc.push(['_setAccount', this.siteId])
71 | }
72 | CNZZ.prototype.trackPageview = function (pageUrl, fromUrl) {
73 | if (!pageUrl || typeof pageUrl !== 'string') {
74 | pageUrl = '/'
75 | }
76 | if (pageUrl.includes('http')) {
77 | var PAGE_CUT = pageUrl.split('/')
78 | var HOST_NAME = PAGE_CUT[0] + '//' + PAGE_CUT[2]
79 | pageUrl = pageUrl.replace(HOST_NAME, '')
80 | }
81 | if (!fromUrl || (fromUrl && typeof fromUrl !== 'string')) {
82 | fromUrl = ''
83 | }
84 | if (typeof fromUrl === 'string' && !fromUrl.includes('http')) {
85 | fromUrl = ''
86 | }
87 | this.setAccount()
88 | if (fromUrl) {
89 | window._czc.push(['_trackPageview', pageUrl, fromUrl])
90 | } else {
91 | window._czc.push(['_trackPageview', pageUrl])
92 | }
93 | if (this.isDebug) {
94 | console.log(
95 | '[vue-cnzz-analytics] track pv done.\nsiteId: ' +
96 | this.siteId +
97 | '\npageUrl: ' +
98 | pageUrl +
99 | '\nfromUrl: ' +
100 | fromUrl
101 | )
102 | }
103 | }
104 | CNZZ.prototype.trackEvent = function (
105 | category,
106 | action,
107 | label,
108 | value,
109 | nodeId
110 | ) {
111 | if (
112 | typeof category !== 'string' ||
113 | typeof action !== 'string' ||
114 | !category ||
115 | !action
116 | ) {
117 | throw new Error(
118 | '[vue-cnzz-analytics] Missing necessary category and operation information, and must be of type string.'
119 | )
120 | }
121 | if (!label || typeof label !== 'string') {
122 | label = ''
123 | }
124 | if (!Number(value)) {
125 | value = 0
126 | }
127 | if (!nodeId || typeof nodeId !== 'string') {
128 | nodeId = ''
129 | }
130 | this.setAccount()
131 | if (nodeId) {
132 | window._czc.push([
133 | '_trackEvent',
134 | category,
135 | action,
136 | label,
137 | value,
138 | nodeId,
139 | ])
140 | } else {
141 | window._czc.push(['_trackEvent', category, action, label, value])
142 | }
143 | if (this.isDebug) {
144 | console.log(
145 | '[vue-cnzz-analytics] track event done.\nsiteId: ' +
146 | this.siteId +
147 | '\ncategory: ' +
148 | category +
149 | '\naction: ' +
150 | action +
151 | '\nlabel: ' +
152 | label +
153 | '\nvalue: ' +
154 | value +
155 | '\nnodeId: ' +
156 | nodeId
157 | )
158 | }
159 | }
160 | return CNZZ
161 | })()
162 |
163 | var PushCNZZ = (function () {
164 | function PushCNZZ(siteIdList, isDebug) {
165 | this.siteIdList = __spreadArray([], siteIdList)
166 | this.isDebug = isDebug
167 | }
168 | PushCNZZ.prototype.init = function () {
169 | var _this = this
170 | this.siteIdList.forEach(function (siteId) {
171 | var SITE = new CNZZ(siteId, _this.isDebug)
172 | SITE.init()
173 | })
174 | }
175 | PushCNZZ.prototype.pv = function (pageUrl, fromUrl) {
176 | var _this = this
177 | this.siteIdList.forEach(function (siteId) {
178 | var SITE = new CNZZ(siteId, _this.isDebug)
179 | SITE.trackPageview(pageUrl, fromUrl)
180 | })
181 | }
182 | PushCNZZ.prototype.event = function (
183 | category,
184 | action,
185 | label,
186 | value,
187 | nodeId
188 | ) {
189 | var _this = this
190 | this.siteIdList.forEach(function (siteId) {
191 | var SITE = new CNZZ(siteId, _this.isDebug)
192 | SITE.trackEvent(category, action, label, value, nodeId)
193 | })
194 | }
195 | return PushCNZZ
196 | })()
197 |
198 | var getVueVersion = function (Vue) {
199 | var version = 2
200 | var VUE_VERSION = String(Vue.version)
201 | if (VUE_VERSION.slice(0, 2) === '2.') {
202 | version = 2
203 | }
204 | if (VUE_VERSION.slice(0, 2) === '3.') {
205 | version = 3
206 | }
207 | return version
208 | }
209 |
210 | var __GLOBAL__ = {
211 | pushCNZZ: {},
212 | }
213 | function usePush() {
214 | function pv(pageUrl, fromUrl) {
215 | return __GLOBAL__.pushCNZZ.pv(pageUrl, fromUrl)
216 | }
217 | function event(category, action, label, value, nodeId) {
218 | return __GLOBAL__.pushCNZZ.event(category, action, label, value, nodeId)
219 | }
220 | return {
221 | pv: pv,
222 | event: event,
223 | }
224 | }
225 | function install(Vue, _a) {
226 | var router = _a.router,
227 | siteIdList = _a.siteIdList,
228 | _b = _a.isDebug,
229 | isDebug = _b === void 0 ? false : _b
230 | if (typeof document === 'undefined' || typeof window === 'undefined') {
231 | return false
232 | }
233 | if (!siteIdList) {
234 | throw new Error(
235 | '[vue-cnzz-analytics] Missing tracking domain ID, add at least one of cnzz analytics.'
236 | )
237 | }
238 | var pushCNZZ = new PushCNZZ(siteIdList, isDebug)
239 | __GLOBAL__.pushCNZZ = pushCNZZ
240 | var VUE_VERSION = getVueVersion(Vue) || 2
241 | switch (VUE_VERSION) {
242 | case 2:
243 | Vue.prototype.$pushCNZZ = pushCNZZ
244 | break
245 | case 3:
246 | Vue.config.globalProperties.$pushCNZZ = pushCNZZ
247 | break
248 | }
249 | if (siteIdList && Array.isArray(siteIdList)) {
250 | pushCNZZ.init()
251 | }
252 | if (router) {
253 | router.afterEach(function () {
254 | var PAGE_URL = window.location.href
255 | pushCNZZ.pv(PAGE_URL)
256 | })
257 | }
258 | }
259 |
260 | exports.default = install
261 | exports.usePush = usePush
262 |
263 | Object.defineProperty(exports, '__esModule', { value: true })
264 | })
265 | //# sourceMappingURL=vue-cnzz-analytics.js.map
266 |
--------------------------------------------------------------------------------
/dist/vue-cnzz-analytics.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"vue-cnzz-analytics.js","sources":["../node_modules/tslib/tslib.es6.js","../src/modules/cnzz.ts","../src/modules/pushCNZZ.ts","../src/modules/getVueVersion.ts","../src/main.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || from);\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","/**\n * 定义基础配置\n * 官方文档 https://developer.umeng.com/docs/67963/detail/74517\n */\nclass CNZZ {\n siteId: number\n isDebug: boolean\n\n constructor(siteId: number = 0, isDebug: boolean = false) {\n this.siteId = siteId\n this.isDebug = isDebug\n }\n\n /**\n * 初始化\n */\n init() {\n window._czc = window._czc ? window._czc : []\n const SCRIPT = document.createElement('script')\n SCRIPT['async'] = true\n SCRIPT[\n 'src'\n ] = `https://s9.cnzz.com/z_stat.php?id=${this.siteId}&web_id=${this.siteId}`\n document.querySelector('head').appendChild(SCRIPT)\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] siteId load done.\\nsiteId: ${this.siteId}`\n )\n }\n }\n\n /**\n * 设置要响应的站点\n */\n setAccount() {\n window._czc.push(['_setAccount', this.siteId])\n }\n\n /**\n * 提交PV、UV\n */\n trackPageview(pageUrl: string, fromUrl?: string) {\n // 如果页面链接没传或者无效链接,则默认为根域名\n if (!pageUrl || typeof pageUrl !== 'string') {\n pageUrl = '/'\n }\n\n // 如果页面链接带上了域名,则需要过滤掉\n if (pageUrl.includes('http')) {\n const PAGE_CUT = pageUrl.split('/')\n const HOST_NAME = `${PAGE_CUT[0]}//${PAGE_CUT[2]}`\n pageUrl = pageUrl.replace(HOST_NAME, '')\n }\n\n // 如果来路url异常,则设置为空\n if (!fromUrl || (fromUrl && typeof fromUrl !== 'string')) {\n fromUrl = ''\n }\n\n // 如果来路url没有带上http/https,也是设置为空\n if (typeof fromUrl === 'string' && !fromUrl.includes('http')) {\n fromUrl = ''\n }\n\n // 设置响应id并提交数据\n this.setAccount()\n\n if (fromUrl) {\n window._czc.push(['_trackPageview', pageUrl, fromUrl])\n } else {\n window._czc.push(['_trackPageview', pageUrl])\n }\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] track pv done.\\nsiteId: ${this.siteId}\\npageUrl: ${pageUrl}\\nfromUrl: ${fromUrl}`\n )\n }\n }\n\n /**\n * 提交点击事件\n */\n trackEvent(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n // 前两个是必填项\n if (\n typeof category !== 'string' ||\n typeof action !== 'string' ||\n !category ||\n !action\n ) {\n throw new Error(\n '[vue-cnzz-analytics] Missing necessary category and operation information, and must be of type string.'\n )\n }\n\n // 重置一些无效的默认值\n if (!label || typeof label !== 'string') {\n label = ''\n }\n\n if (!Number(value)) {\n value = 0\n }\n\n if (!nodeId || typeof nodeId !== 'string') {\n nodeId = ''\n }\n\n // 设置响应id并提交数据\n this.setAccount()\n\n if (nodeId) {\n window._czc.push(['_trackEvent', category, action, label, value, nodeId])\n } else {\n window._czc.push(['_trackEvent', category, action, label, value])\n }\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] track event done.\\nsiteId: ${this.siteId}\\ncategory: ${category}\\naction: ${action}\\nlabel: ${label}\\nvalue: ${value}\\nnodeId: ${nodeId}`\n )\n }\n }\n}\n\nexport default CNZZ\n","import CNZZ from '@m/cnzz'\n\n/**\n * 定义推送操作\n */\nclass PushCNZZ {\n siteIdList: number[]\n isDebug: boolean\n\n constructor(siteIdList: number[], isDebug: boolean) {\n this.siteIdList = [...siteIdList]\n this.isDebug = isDebug\n }\n\n /**\n * 批量部署站点\n */\n init() {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.init()\n })\n }\n\n /**\n * 批量提交pv上报\n */\n pv(pageUrl: string, fromUrl?: string) {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.trackPageview(pageUrl, fromUrl)\n })\n }\n\n /**\n * 批量提交事件上报\n */\n event(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.trackEvent(category, action, label, value, nodeId)\n })\n }\n}\n\nexport default PushCNZZ\n","import type { Vue } from '@/types'\n\n/**\n * 获取Vue的版本\n * @return 2=Vue2.x, 3=Vue3.x\n */\nconst getVueVersion = (Vue: Vue): number => {\n let version: number = 2\n\n // 获取Vue的版本号\n const VUE_VERSION: string = String(Vue.version)\n\n // Vue 2.x\n if (VUE_VERSION.slice(0, 2) === '2.') {\n version = 2\n }\n\n // Vue 3.x\n if (VUE_VERSION.slice(0, 2) === '3.') {\n version = 3\n }\n\n return version\n}\n\nexport default getVueVersion\n","import PushCNZZ from '@m/pushCNZZ'\nimport getVueVersion from '@m/getVueVersion'\nimport type { Options, Vue } from '@/types'\n\n/**\n * 全局的数据\n */\nconst __GLOBAL__ = {\n pushCNZZ: {} as PushCNZZ,\n}\n\n/**\n * 暴露 Hooks\n * @description 解决 Vue 3.0 使用全局变量很麻烦的问题\n * @example\n * import { usePush } from 'vue-cnzz-analytics'\n * const cnzz = usePush();\n * cnzz.pv('/');\n */\nexport function usePush() {\n // 提交 pv\n function pv(pageUrl: string, fromUrl?: string) {\n return __GLOBAL__.pushCNZZ.pv(pageUrl, fromUrl)\n }\n\n // 提交事件\n function event(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n return __GLOBAL__.pushCNZZ.event(category, action, label, value, nodeId)\n }\n\n return {\n pv,\n event,\n }\n}\n\n/**\n * 定义插件\n */\nexport default function install(\n Vue: Vue,\n { router, siteIdList, isDebug = false }: Partial\n) {\n /**\n * 一些环境和参数的检查\n */\n if (typeof document === 'undefined' || typeof window === 'undefined') {\n return false\n }\n\n if (!siteIdList) {\n throw new Error(\n '[vue-cnzz-analytics] Missing tracking domain ID, add at least one of cnzz analytics.'\n )\n }\n\n /**\n * 挂载推送的方法\n */\n const pushCNZZ = new PushCNZZ(siteIdList, isDebug)\n __GLOBAL__.pushCNZZ = pushCNZZ\n\n /**\n * 挂载全局变量到 Vue 上\n * 获取Vue版本(获取失败则默认为2)\n */\n const VUE_VERSION: number = getVueVersion(Vue) || 2\n switch (VUE_VERSION) {\n case 2:\n Vue.prototype.$pushCNZZ = pushCNZZ\n break\n case 3:\n Vue.config.globalProperties.$pushCNZZ = pushCNZZ\n break\n }\n\n /**\n * 部署站点并初始化\n */\n if (siteIdList && Array.isArray(siteIdList)) {\n pushCNZZ.init()\n }\n\n /**\n * 路由切换时执行PV上报\n */\n if (router) {\n router.afterEach(() => {\n // 获取要上报的链接(当前版本不需要拼接了)\n const PAGE_URL: string = window.location.href\n\n // 上报数据\n pushCNZZ.pv(PAGE_URL)\n })\n }\n}\n"],"names":["__spreadArray","to","from","pack","arguments","length","i","l","ar","Array","prototype","slice","call","concat"],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/vue-cnzz-analytics.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * name: vue-cnzz-analytics
3 | * version: v2.2.0
4 | * author: chengpeiquan
5 | */
6 | !(function (t, e) {
7 | 'object' == typeof exports && 'undefined' != typeof module
8 | ? e(exports)
9 | : 'function' == typeof define && define.amd
10 | ? define(['exports'], e)
11 | : e(
12 | ((t =
13 | 'undefined' != typeof globalThis
14 | ? globalThis
15 | : t || self).cnzzAnalytics = {})
16 | )
17 | })(this, function (t) {
18 | 'use strict'
19 | var e = (function () {
20 | function t(t, e) {
21 | void 0 === t && (t = 0),
22 | void 0 === e && (e = !1),
23 | (this.siteId = t),
24 | (this.isDebug = e)
25 | }
26 | return (
27 | (t.prototype.init = function () {
28 | window._czc = window._czc ? window._czc : []
29 | var t = document.createElement('script')
30 | ;(t.async = !0),
31 | (t.src =
32 | 'https://s9.cnzz.com/z_stat.php?id=' +
33 | this.siteId +
34 | '&web_id=' +
35 | this.siteId),
36 | document.querySelector('head').appendChild(t),
37 | this.isDebug &&
38 | console.log(
39 | '[vue-cnzz-analytics] siteId load done.\nsiteId: ' +
40 | this.siteId
41 | )
42 | }),
43 | (t.prototype.setAccount = function () {
44 | window._czc.push(['_setAccount', this.siteId])
45 | }),
46 | (t.prototype.trackPageview = function (t, e) {
47 | if (((t && 'string' == typeof t) || (t = '/'), t.includes('http'))) {
48 | var n = t.split('/'),
49 | i = n[0] + '//' + n[2]
50 | t = t.replace(i, '')
51 | }
52 | ;(!e || (e && 'string' != typeof e)) && (e = ''),
53 | 'string' != typeof e || e.includes('http') || (e = ''),
54 | this.setAccount(),
55 | e
56 | ? window._czc.push(['_trackPageview', t, e])
57 | : window._czc.push(['_trackPageview', t]),
58 | this.isDebug &&
59 | console.log(
60 | '[vue-cnzz-analytics] track pv done.\nsiteId: ' +
61 | this.siteId +
62 | '\npageUrl: ' +
63 | t +
64 | '\nfromUrl: ' +
65 | e
66 | )
67 | }),
68 | (t.prototype.trackEvent = function (t, e, n, i, o) {
69 | if ('string' != typeof t || 'string' != typeof e || !t || !e)
70 | throw new Error(
71 | '[vue-cnzz-analytics] Missing necessary category and operation information, and must be of type string.'
72 | )
73 | ;(n && 'string' == typeof n) || (n = ''),
74 | Number(i) || (i = 0),
75 | (o && 'string' == typeof o) || (o = ''),
76 | this.setAccount(),
77 | o
78 | ? window._czc.push(['_trackEvent', t, e, n, i, o])
79 | : window._czc.push(['_trackEvent', t, e, n, i]),
80 | this.isDebug &&
81 | console.log(
82 | '[vue-cnzz-analytics] track event done.\nsiteId: ' +
83 | this.siteId +
84 | '\ncategory: ' +
85 | t +
86 | '\naction: ' +
87 | e +
88 | '\nlabel: ' +
89 | n +
90 | '\nvalue: ' +
91 | i +
92 | '\nnodeId: ' +
93 | o
94 | )
95 | }),
96 | t
97 | )
98 | })(),
99 | n = (function () {
100 | function t(t, e) {
101 | ;(this.siteIdList = (function (t, e, n) {
102 | if (n || 2 === arguments.length)
103 | for (var i, o = 0, s = e.length; o < s; o++)
104 | (!i && o in e) ||
105 | (i || (i = Array.prototype.slice.call(e, 0, o)), (i[o] = e[o]))
106 | return t.concat(i || e)
107 | })([], t)),
108 | (this.isDebug = e)
109 | }
110 | return (
111 | (t.prototype.init = function () {
112 | var t = this
113 | this.siteIdList.forEach(function (n) {
114 | new e(n, t.isDebug).init()
115 | })
116 | }),
117 | (t.prototype.pv = function (t, n) {
118 | var i = this
119 | this.siteIdList.forEach(function (o) {
120 | new e(o, i.isDebug).trackPageview(t, n)
121 | })
122 | }),
123 | (t.prototype.event = function (t, n, i, o, s) {
124 | var c = this
125 | this.siteIdList.forEach(function (r) {
126 | new e(r, c.isDebug).trackEvent(t, n, i, o, s)
127 | })
128 | }),
129 | t
130 | )
131 | })(),
132 | i = { pushCNZZ: {} }
133 | ;(t.default = function (t, e) {
134 | var o = e.router,
135 | s = e.siteIdList,
136 | c = e.isDebug,
137 | r = void 0 !== c && c
138 | if ('undefined' == typeof document || 'undefined' == typeof window)
139 | return !1
140 | if (!s)
141 | throw new Error(
142 | '[vue-cnzz-analytics] Missing tracking domain ID, add at least one of cnzz analytics.'
143 | )
144 | var u = new n(s, r)
145 | switch (
146 | ((i.pushCNZZ = u),
147 | (function (t) {
148 | var e = 2,
149 | n = String(t.version)
150 | return (
151 | '2.' === n.slice(0, 2) && (e = 2),
152 | '3.' === n.slice(0, 2) && (e = 3),
153 | e
154 | )
155 | })(t) || 2)
156 | ) {
157 | case 2:
158 | t.prototype.$pushCNZZ = u
159 | break
160 | case 3:
161 | t.config.globalProperties.$pushCNZZ = u
162 | }
163 | s && Array.isArray(s) && u.init(),
164 | o &&
165 | o.afterEach(function () {
166 | var t = window.location.href
167 | u.pv(t)
168 | })
169 | }),
170 | (t.usePush = function () {
171 | return {
172 | pv: function (t, e) {
173 | return i.pushCNZZ.pv(t, e)
174 | },
175 | event: function (t, e, n, o, s) {
176 | return i.pushCNZZ.event(t, e, n, o, s)
177 | },
178 | }
179 | }),
180 | Object.defineProperty(t, '__esModule', { value: !0 })
181 | })
182 | //# sourceMappingURL=vue-cnzz-analytics.min.js.map
183 |
--------------------------------------------------------------------------------
/dist/vue-cnzz-analytics.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"vue-cnzz-analytics.min.js","sources":["../src/modules/cnzz.ts","../src/modules/pushCNZZ.ts","../node_modules/tslib/tslib.es6.js","../src/main.ts","../src/modules/getVueVersion.ts"],"sourcesContent":["/**\n * 定义基础配置\n * 官方文档 https://developer.umeng.com/docs/67963/detail/74517\n */\nclass CNZZ {\n siteId: number\n isDebug: boolean\n\n constructor(siteId: number = 0, isDebug: boolean = false) {\n this.siteId = siteId\n this.isDebug = isDebug\n }\n\n /**\n * 初始化\n */\n init() {\n window._czc = window._czc ? window._czc : []\n const SCRIPT = document.createElement('script')\n SCRIPT['async'] = true\n SCRIPT[\n 'src'\n ] = `https://s9.cnzz.com/z_stat.php?id=${this.siteId}&web_id=${this.siteId}`\n document.querySelector('head').appendChild(SCRIPT)\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] siteId load done.\\nsiteId: ${this.siteId}`\n )\n }\n }\n\n /**\n * 设置要响应的站点\n */\n setAccount() {\n window._czc.push(['_setAccount', this.siteId])\n }\n\n /**\n * 提交PV、UV\n */\n trackPageview(pageUrl: string, fromUrl?: string) {\n // 如果页面链接没传或者无效链接,则默认为根域名\n if (!pageUrl || typeof pageUrl !== 'string') {\n pageUrl = '/'\n }\n\n // 如果页面链接带上了域名,则需要过滤掉\n if (pageUrl.includes('http')) {\n const PAGE_CUT = pageUrl.split('/')\n const HOST_NAME = `${PAGE_CUT[0]}//${PAGE_CUT[2]}`\n pageUrl = pageUrl.replace(HOST_NAME, '')\n }\n\n // 如果来路url异常,则设置为空\n if (!fromUrl || (fromUrl && typeof fromUrl !== 'string')) {\n fromUrl = ''\n }\n\n // 如果来路url没有带上http/https,也是设置为空\n if (typeof fromUrl === 'string' && !fromUrl.includes('http')) {\n fromUrl = ''\n }\n\n // 设置响应id并提交数据\n this.setAccount()\n\n if (fromUrl) {\n window._czc.push(['_trackPageview', pageUrl, fromUrl])\n } else {\n window._czc.push(['_trackPageview', pageUrl])\n }\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] track pv done.\\nsiteId: ${this.siteId}\\npageUrl: ${pageUrl}\\nfromUrl: ${fromUrl}`\n )\n }\n }\n\n /**\n * 提交点击事件\n */\n trackEvent(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n // 前两个是必填项\n if (\n typeof category !== 'string' ||\n typeof action !== 'string' ||\n !category ||\n !action\n ) {\n throw new Error(\n '[vue-cnzz-analytics] Missing necessary category and operation information, and must be of type string.'\n )\n }\n\n // 重置一些无效的默认值\n if (!label || typeof label !== 'string') {\n label = ''\n }\n\n if (!Number(value)) {\n value = 0\n }\n\n if (!nodeId || typeof nodeId !== 'string') {\n nodeId = ''\n }\n\n // 设置响应id并提交数据\n this.setAccount()\n\n if (nodeId) {\n window._czc.push(['_trackEvent', category, action, label, value, nodeId])\n } else {\n window._czc.push(['_trackEvent', category, action, label, value])\n }\n\n if (this.isDebug) {\n console.log(\n `[vue-cnzz-analytics] track event done.\\nsiteId: ${this.siteId}\\ncategory: ${category}\\naction: ${action}\\nlabel: ${label}\\nvalue: ${value}\\nnodeId: ${nodeId}`\n )\n }\n }\n}\n\nexport default CNZZ\n","import CNZZ from '@m/cnzz'\n\n/**\n * 定义推送操作\n */\nclass PushCNZZ {\n siteIdList: number[]\n isDebug: boolean\n\n constructor(siteIdList: number[], isDebug: boolean) {\n this.siteIdList = [...siteIdList]\n this.isDebug = isDebug\n }\n\n /**\n * 批量部署站点\n */\n init() {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.init()\n })\n }\n\n /**\n * 批量提交pv上报\n */\n pv(pageUrl: string, fromUrl?: string) {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.trackPageview(pageUrl, fromUrl)\n })\n }\n\n /**\n * 批量提交事件上报\n */\n event(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n this.siteIdList.forEach((siteId: number) => {\n const SITE = new CNZZ(siteId, this.isDebug)\n SITE.trackEvent(category, action, label, value, nodeId)\n })\n }\n}\n\nexport default PushCNZZ\n","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || from);\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","import PushCNZZ from '@m/pushCNZZ'\nimport getVueVersion from '@m/getVueVersion'\nimport type { Options, Vue } from '@/types'\n\n/**\n * 全局的数据\n */\nconst __GLOBAL__ = {\n pushCNZZ: {} as PushCNZZ,\n}\n\n/**\n * 暴露 Hooks\n * @description 解决 Vue 3.0 使用全局变量很麻烦的问题\n * @example\n * import { usePush } from 'vue-cnzz-analytics'\n * const cnzz = usePush();\n * cnzz.pv('/');\n */\nexport function usePush() {\n // 提交 pv\n function pv(pageUrl: string, fromUrl?: string) {\n return __GLOBAL__.pushCNZZ.pv(pageUrl, fromUrl)\n }\n\n // 提交事件\n function event(\n category: string,\n action: string,\n label: string,\n value: number,\n nodeId: string\n ) {\n return __GLOBAL__.pushCNZZ.event(category, action, label, value, nodeId)\n }\n\n return {\n pv,\n event,\n }\n}\n\n/**\n * 定义插件\n */\nexport default function install(\n Vue: Vue,\n { router, siteIdList, isDebug = false }: Partial\n) {\n /**\n * 一些环境和参数的检查\n */\n if (typeof document === 'undefined' || typeof window === 'undefined') {\n return false\n }\n\n if (!siteIdList) {\n throw new Error(\n '[vue-cnzz-analytics] Missing tracking domain ID, add at least one of cnzz analytics.'\n )\n }\n\n /**\n * 挂载推送的方法\n */\n const pushCNZZ = new PushCNZZ(siteIdList, isDebug)\n __GLOBAL__.pushCNZZ = pushCNZZ\n\n /**\n * 挂载全局变量到 Vue 上\n * 获取Vue版本(获取失败则默认为2)\n */\n const VUE_VERSION: number = getVueVersion(Vue) || 2\n switch (VUE_VERSION) {\n case 2:\n Vue.prototype.$pushCNZZ = pushCNZZ\n break\n case 3:\n Vue.config.globalProperties.$pushCNZZ = pushCNZZ\n break\n }\n\n /**\n * 部署站点并初始化\n */\n if (siteIdList && Array.isArray(siteIdList)) {\n pushCNZZ.init()\n }\n\n /**\n * 路由切换时执行PV上报\n */\n if (router) {\n router.afterEach(() => {\n // 获取要上报的链接(当前版本不需要拼接了)\n const PAGE_URL: string = window.location.href\n\n // 上报数据\n pushCNZZ.pv(PAGE_URL)\n })\n }\n}\n","import type { Vue } from '@/types'\n\n/**\n * 获取Vue的版本\n * @return 2=Vue2.x, 3=Vue3.x\n */\nconst getVueVersion = (Vue: Vue): number => {\n let version: number = 2\n\n // 获取Vue的版本号\n const VUE_VERSION: string = String(Vue.version)\n\n // Vue 2.x\n if (VUE_VERSION.slice(0, 2) === '2.') {\n version = 2\n }\n\n // Vue 3.x\n if (VUE_VERSION.slice(0, 2) === '3.') {\n version = 3\n }\n\n return version\n}\n\nexport default getVueVersion\n"],"names":["siteId","isDebug","this","CNZZ","window","_czc","SCRIPT","document","createElement","querySelector","appendChild","console","log","push","pageUrl","fromUrl","includes","PAGE_CUT","split","HOST_NAME","replace","setAccount","category","action","label","value","nodeId","Error","Number","siteIdList","to","from","pack","arguments","length","ar","i","l","Array","prototype","slice","call","concat","PushCNZZ","forEach","_this","init","trackPageview","trackEvent","__GLOBAL__","pushCNZZ","Vue","_a","router","_b","version","VUE_VERSION","String","getVueVersion","$pushCNZZ","config","globalProperties","isArray","afterEach","PAGE_URL","location","href","pv","event"],"mappings":"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"}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-cnzz-analytics",
3 | "version": "2.2.0",
4 | "description": "A data collection tool that supports reporting of single-page application data built by Vue 3.0 & 2.0 & VuePress, based on cnzz statistics.",
5 | "main": "dist/vue-cnzz-analytics.min.js",
6 | "types": "vue-cnzz-analytics.d.ts",
7 | "scripts": {
8 | "build": "rollup -c rollup.config.ts",
9 | "lint": "eslint src --ext .js,.ts",
10 | "prettier": "prettier --write src"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/analyticsjs/vue-cnzz-analytics.git"
15 | },
16 | "keywords": [
17 | "cnzz",
18 | "vue cnzz",
19 | "vue umeng",
20 | "vue analytics",
21 | "vuepress analytics",
22 | "vue 3.0 cnzz",
23 | "vue 3.0 umeng",
24 | "vue 3.0 analytics",
25 | "spa analytics",
26 | "cnzz统计",
27 | "umeng统计",
28 | "vuepress统计",
29 | "友盟统计"
30 | ],
31 | "author": "chengpeiquan",
32 | "homepage": "https://github.com/analyticsjs/vue-cnzz-analytics",
33 | "license": "MIT",
34 | "devDependencies": {
35 | "@babel/core": "^7.11.1",
36 | "@babel/plugin-proposal-class-properties": "^7.10.4",
37 | "@babel/preset-env": "^7.11.0",
38 | "@babel/preset-typescript": "^7.10.4",
39 | "@rollup/plugin-babel": "^5.2.0",
40 | "@rollup/plugin-commonjs": "^15.0.0",
41 | "@rollup/plugin-json": "^4.1.0",
42 | "@rollup/plugin-node-resolve": "^9.0.0",
43 | "@types/babel__core": "^7.1.9",
44 | "@typescript-eslint/eslint-plugin": "^4.20.0",
45 | "@typescript-eslint/parser": "^4.20.0",
46 | "chalk": "^4.1.1",
47 | "eslint": "^7.23.0",
48 | "eslint-config-prettier": "^8.3.0",
49 | "eslint-plugin-prettier": "^3.4.0",
50 | "husky": "4.2.3",
51 | "lint-staged": "^11.0.0",
52 | "prettier": "^2.3.1",
53 | "rollup": "^2.44.0",
54 | "rollup-plugin-banner2": "^1.2.2",
55 | "rollup-plugin-terser": "^7.0.0",
56 | "rollup-plugin-typescript2": "^0.30.0",
57 | "tslib": "^2.3.0",
58 | "typescript": "^4.0.2"
59 | },
60 | "husky": {
61 | "hooks": {
62 | "pre-commit": "lint-staged",
63 | "commit-msg": "node scripts/verifyCommit.js"
64 | }
65 | },
66 | "lint-staged": {
67 | "*.{js,jsx,vue,ts,tsx}": [
68 | "prettier --write",
69 | "eslint --fix",
70 | "git add"
71 | ]
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/rollup.config.ts:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve'
2 | import babel from '@rollup/plugin-babel'
3 | import commonjs from '@rollup/plugin-commonjs'
4 | import json from '@rollup/plugin-json'
5 | import { terser } from 'rollup-plugin-terser'
6 | import banner2 from 'rollup-plugin-banner2'
7 | import typescript from 'rollup-plugin-typescript2'
8 | import pkg from './package.json'
9 |
10 | // 输出选项
11 | const outputOptions = {
12 | format: 'umd',
13 | name: 'cnzzAnalytics',
14 | exports: 'named',
15 | sourcemap: true
16 | }
17 |
18 | export default {
19 | input: 'src/main.ts',
20 | output: [
21 | {
22 | file: `dist/vue-cnzz-analytics.js`,
23 | ...outputOptions
24 | },
25 | {
26 | file: `dist/vue-cnzz-analytics.min.js`,
27 | plugins: [
28 | terser()
29 | ],
30 | ...outputOptions
31 | }
32 | ],
33 | plugins: [
34 | resolve({
35 | browser: true
36 | }),
37 |
38 | babel({
39 | babelHelpers: 'bundled'
40 | }),
41 |
42 | commonjs(),
43 |
44 | json(),
45 |
46 | typescript(),
47 |
48 | banner2(() => `/*!\n * name: ${pkg.name}\n * version: v${pkg.version}\n * author: ${pkg.author}\n */\n`)
49 | ]
50 | };
51 |
--------------------------------------------------------------------------------
/scripts/verifyCommit.js:
--------------------------------------------------------------------------------
1 | // Invoked on the commit-msg git hook by yorkie.
2 |
3 | const fs = require('fs')
4 | const chalk = require('chalk')
5 | const msgPath = process.env.HUSKY_GIT_PARAMS
6 | const msg = fs.readFileSync(msgPath, 'utf-8').trim()
7 |
8 | const commitRE =
9 | /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
10 |
11 | if (!commitRE.test(msg)) {
12 | console.log()
13 | console.error(
14 | ` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
15 | `invalid commit message format.`
16 | )}\n\n` +
17 | chalk.red(
18 | ` Proper commit message format is required for automated changelog generation. Examples:\n\n`
19 | ) +
20 | ` ${chalk.green(`feat(compiler): add 'comments' option`)}\n` +
21 | ` ${chalk.green(
22 | `fix(v-model): handle events on blur (close #28)`
23 | )}\n\n` +
24 | chalk.red(` See .github/commit-convention.md for more details.\n`)
25 | )
26 | process.exit(1)
27 | }
28 |
--------------------------------------------------------------------------------
/src/global.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | export {}
3 |
4 | declare global {
5 | interface Window {
6 | _czc: any
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import PushCNZZ from '@m/pushCNZZ'
2 | import getVueVersion from '@m/getVueVersion'
3 | import type { Options, Vue } from '@/types'
4 |
5 | /**
6 | * 全局的数据
7 | */
8 | const __GLOBAL__ = {
9 | pushCNZZ: {} as PushCNZZ,
10 | }
11 |
12 | /**
13 | * 暴露 Hooks
14 | * @description 解决 Vue 3.0 使用全局变量很麻烦的问题
15 | * @example
16 | * import { usePush } from 'vue-cnzz-analytics'
17 | * const cnzz = usePush();
18 | * cnzz.pv('/');
19 | */
20 | export function usePush() {
21 | // 提交 pv
22 | function pv(pageUrl: string, fromUrl?: string) {
23 | return __GLOBAL__.pushCNZZ.pv(pageUrl, fromUrl)
24 | }
25 |
26 | // 提交事件
27 | function event(
28 | category: string,
29 | action: string,
30 | label: string,
31 | value: number,
32 | nodeId: string
33 | ) {
34 | return __GLOBAL__.pushCNZZ.event(category, action, label, value, nodeId)
35 | }
36 |
37 | return {
38 | pv,
39 | event,
40 | }
41 | }
42 |
43 | /**
44 | * 定义插件
45 | */
46 | export default function install(
47 | Vue: Vue,
48 | { router, siteIdList, isDebug = false }: Partial
49 | ) {
50 | /**
51 | * 一些环境和参数的检查
52 | */
53 | if (typeof document === 'undefined' || typeof window === 'undefined') {
54 | return false
55 | }
56 |
57 | if (!siteIdList) {
58 | throw new Error(
59 | '[vue-cnzz-analytics] Missing tracking domain ID, add at least one of cnzz analytics.'
60 | )
61 | }
62 |
63 | /**
64 | * 挂载推送的方法
65 | */
66 | const pushCNZZ = new PushCNZZ(siteIdList, isDebug)
67 | __GLOBAL__.pushCNZZ = pushCNZZ
68 |
69 | /**
70 | * 挂载全局变量到 Vue 上
71 | * 获取Vue版本(获取失败则默认为2)
72 | */
73 | const VUE_VERSION: number = getVueVersion(Vue) || 2
74 | switch (VUE_VERSION) {
75 | case 2:
76 | Vue.prototype.$pushCNZZ = pushCNZZ
77 | break
78 | case 3:
79 | Vue.config.globalProperties.$pushCNZZ = pushCNZZ
80 | break
81 | }
82 |
83 | /**
84 | * 部署站点并初始化
85 | */
86 | if (siteIdList && Array.isArray(siteIdList)) {
87 | pushCNZZ.init()
88 | }
89 |
90 | /**
91 | * 路由切换时执行PV上报
92 | */
93 | if (router) {
94 | router.afterEach(() => {
95 | // 获取要上报的链接(当前版本不需要拼接了)
96 | const PAGE_URL: string = window.location.href
97 |
98 | // 上报数据
99 | pushCNZZ.pv(PAGE_URL)
100 | })
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/modules/cnzz.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 定义基础配置
3 | * 官方文档 https://developer.umeng.com/docs/67963/detail/74517
4 | */
5 | class CNZZ {
6 | siteId: number
7 | isDebug: boolean
8 |
9 | constructor(siteId: number = 0, isDebug: boolean = false) {
10 | this.siteId = siteId
11 | this.isDebug = isDebug
12 | }
13 |
14 | /**
15 | * 初始化
16 | */
17 | init() {
18 | window._czc = window._czc ? window._czc : []
19 | const SCRIPT = document.createElement('script')
20 | SCRIPT['async'] = true
21 | SCRIPT[
22 | 'src'
23 | ] = `https://s9.cnzz.com/z_stat.php?id=${this.siteId}&web_id=${this.siteId}`
24 | document.querySelector('head').appendChild(SCRIPT)
25 |
26 | if (this.isDebug) {
27 | console.log(
28 | `[vue-cnzz-analytics] siteId load done.\nsiteId: ${this.siteId}`
29 | )
30 | }
31 | }
32 |
33 | /**
34 | * 设置要响应的站点
35 | */
36 | setAccount() {
37 | window._czc.push(['_setAccount', this.siteId])
38 | }
39 |
40 | /**
41 | * 提交PV、UV
42 | */
43 | trackPageview(pageUrl: string, fromUrl?: string) {
44 | // 如果页面链接没传或者无效链接,则默认为根域名
45 | if (!pageUrl || typeof pageUrl !== 'string') {
46 | pageUrl = '/'
47 | }
48 |
49 | // 如果页面链接带上了域名,则需要过滤掉
50 | if (pageUrl.includes('http')) {
51 | const PAGE_CUT = pageUrl.split('/')
52 | const HOST_NAME = `${PAGE_CUT[0]}//${PAGE_CUT[2]}`
53 | pageUrl = pageUrl.replace(HOST_NAME, '')
54 | }
55 |
56 | // 如果来路url异常,则设置为空
57 | if (!fromUrl || (fromUrl && typeof fromUrl !== 'string')) {
58 | fromUrl = ''
59 | }
60 |
61 | // 如果来路url没有带上http/https,也是设置为空
62 | if (typeof fromUrl === 'string' && !fromUrl.includes('http')) {
63 | fromUrl = ''
64 | }
65 |
66 | // 设置响应id并提交数据
67 | this.setAccount()
68 |
69 | if (fromUrl) {
70 | window._czc.push(['_trackPageview', pageUrl, fromUrl])
71 | } else {
72 | window._czc.push(['_trackPageview', pageUrl])
73 | }
74 |
75 | if (this.isDebug) {
76 | console.log(
77 | `[vue-cnzz-analytics] track pv done.\nsiteId: ${this.siteId}\npageUrl: ${pageUrl}\nfromUrl: ${fromUrl}`
78 | )
79 | }
80 | }
81 |
82 | /**
83 | * 提交点击事件
84 | */
85 | trackEvent(
86 | category: string,
87 | action: string,
88 | label: string,
89 | value: number,
90 | nodeId: string
91 | ) {
92 | // 前两个是必填项
93 | if (
94 | typeof category !== 'string' ||
95 | typeof action !== 'string' ||
96 | !category ||
97 | !action
98 | ) {
99 | throw new Error(
100 | '[vue-cnzz-analytics] Missing necessary category and operation information, and must be of type string.'
101 | )
102 | }
103 |
104 | // 重置一些无效的默认值
105 | if (!label || typeof label !== 'string') {
106 | label = ''
107 | }
108 |
109 | if (!Number(value)) {
110 | value = 0
111 | }
112 |
113 | if (!nodeId || typeof nodeId !== 'string') {
114 | nodeId = ''
115 | }
116 |
117 | // 设置响应id并提交数据
118 | this.setAccount()
119 |
120 | if (nodeId) {
121 | window._czc.push(['_trackEvent', category, action, label, value, nodeId])
122 | } else {
123 | window._czc.push(['_trackEvent', category, action, label, value])
124 | }
125 |
126 | if (this.isDebug) {
127 | console.log(
128 | `[vue-cnzz-analytics] track event done.\nsiteId: ${this.siteId}\ncategory: ${category}\naction: ${action}\nlabel: ${label}\nvalue: ${value}\nnodeId: ${nodeId}`
129 | )
130 | }
131 | }
132 | }
133 |
134 | export default CNZZ
135 |
--------------------------------------------------------------------------------
/src/modules/getVueVersion.ts:
--------------------------------------------------------------------------------
1 | import type { Vue } from '@/types'
2 |
3 | /**
4 | * 获取Vue的版本
5 | * @return 2=Vue2.x, 3=Vue3.x
6 | */
7 | const getVueVersion = (Vue: Vue): number => {
8 | let version: number = 2
9 |
10 | // 获取Vue的版本号
11 | const VUE_VERSION: string = String(Vue.version)
12 |
13 | // Vue 2.x
14 | if (VUE_VERSION.slice(0, 2) === '2.') {
15 | version = 2
16 | }
17 |
18 | // Vue 3.x
19 | if (VUE_VERSION.slice(0, 2) === '3.') {
20 | version = 3
21 | }
22 |
23 | return version
24 | }
25 |
26 | export default getVueVersion
27 |
--------------------------------------------------------------------------------
/src/modules/pushCNZZ.ts:
--------------------------------------------------------------------------------
1 | import CNZZ from '@m/cnzz'
2 |
3 | /**
4 | * 定义推送操作
5 | */
6 | class PushCNZZ {
7 | siteIdList: number[]
8 | isDebug: boolean
9 |
10 | constructor(siteIdList: number[], isDebug: boolean) {
11 | this.siteIdList = [...siteIdList]
12 | this.isDebug = isDebug
13 | }
14 |
15 | /**
16 | * 批量部署站点
17 | */
18 | init() {
19 | this.siteIdList.forEach((siteId: number) => {
20 | const SITE = new CNZZ(siteId, this.isDebug)
21 | SITE.init()
22 | })
23 | }
24 |
25 | /**
26 | * 批量提交pv上报
27 | */
28 | pv(pageUrl: string, fromUrl?: string) {
29 | this.siteIdList.forEach((siteId: number) => {
30 | const SITE = new CNZZ(siteId, this.isDebug)
31 | SITE.trackPageview(pageUrl, fromUrl)
32 | })
33 | }
34 |
35 | /**
36 | * 批量提交事件上报
37 | */
38 | event(
39 | category: string,
40 | action: string,
41 | label: string,
42 | value: number,
43 | nodeId: string
44 | ) {
45 | this.siteIdList.forEach((siteId: number) => {
46 | const SITE = new CNZZ(siteId, this.isDebug)
47 | SITE.trackEvent(category, action, label, value, nodeId)
48 | })
49 | }
50 | }
51 |
52 | export default PushCNZZ
53 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import PushCNZZ from '@m/pushCNZZ'
2 |
3 | export interface Options {
4 | router: any
5 | siteIdList: number[]
6 | isDebug: boolean
7 | }
8 |
9 | export interface Vue {
10 | prototype: any
11 | $pushCNZZ: PushCNZZ
12 | version: number | string
13 | config: any
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5",
4 | "module": "ES2015",
5 | "allowSyntheticDefaultImports": true,
6 | "noImplicitAny": true,
7 | "removeComments": true,
8 | "preserveConstEnums": true,
9 | "sourceMap": true,
10 | "baseUrl": ".",
11 | "paths": {
12 | "@/*": [
13 | "src/*"
14 | ],
15 | "@m/*": [
16 | "src/modules/*"
17 | ]
18 | },
19 | "declaration": true,
20 | "declarationDir": "./dist"
21 | },
22 | "include": [
23 | "src/**/*.ts"
24 | ],
25 | "exclude": [
26 | "node_modules"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/vue-cnzz-analytics.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'vue-cnzz-analytics'
--------------------------------------------------------------------------------