vue-yandex-metrika
vue-yandex-metrika copied to clipboard
$metrika is undefined
Hey.
-
vue-yandex-metrika
version: 1.7.2 -
node
version: 10.13.0 -
npm
(oryarn
) version: 6.4.1
Relevant code or config
handleImport() {
this.$metrika.reachGoal('import')
this.showModal(this.$lang.actions.import, 'import')
},
Problem description: After call method handleImport():
https://sentry.io/share/issue/9c0025640c52451baaf56572326847bf/
You probably have a race condition. You think that the prototype $metrika is already available but it is not. You can check that by adding this to your URL:
/?_ym_debug=1
If the error occurs before "PageView. Counter XXXXXXXX . URL: ............" you have a race condition problem.
I'm using the reachGoal function in a action (Vuex) and I have the same issue. You could use a try and catch block.
I am experiencing the same issue had to like this in all places
mounted() {
setTimeout(() => {
//call my plugin code with golas here
}, 2000)
}
which is not desirable solution
Setting everywhere a timeout is not a great solution. Especially when the DOM is still not rendered after 2 seconds for whatever reason (theoretically). After some reasearch and reading the Vue.js documentation, I came to the solution that you have to use the mounted and the $nextTick function in combination to be sure that the DOM is fully rendered (and so the Yandex Metrika script):
Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted:
Source: Vue.js documentation
Just implement their example:
mounted: function () { this.$nextTick(function () { // Call Metrika here }) }
After some tests, it seems that my try-and-catch-block is not triggered anymore. It works and it is a cleaner solution than a timer. Hopefully I could help :)
@picarsite yes $nextTick is a common way to ensure the Vue's DOM operations are done, but if we look deeper into YM docs - https://yandex.com/support/metrica/code/counter-initialize.html#counter-initialize__check-initialize
we could try to achieve this with:
- create internal array for events that were called by the consumer while YM was not operating
- add
triggerEvent: true
in config https://github.com/vchaptsev/vue-yandex-metrika/blob/master/src/config.js#L14 - add to init code
document.addEventListener('yacounter${this.config.id}inited', () => {
//callback to execute all items from internal array for events
});
@picarsite yes $nextTick is a common way to ensure the Vue's DOM operations are done, but if we look deeper into YM docs - https://yandex.com/support/metrica/code/counter-initialize.html#counter-initialize__check-initialize
we could try to achieve this with:
- create internal array for events that were called by the consumer while YM was not operating
- add
triggerEvent: true
in config https://github.com/vchaptsev/vue-yandex-metrika/blob/master/src/config.js#L14- add to init code
document.addEventListener('yacounter${this.config.id}inited', () => { //callback to execute all items from internal array for events });
...
If it doesn't give results in localhost
set env: 'production'
in options of VueYandexMetrika in main.js
Cause warning
Vue.use(VueYandexMetrika, {
id: XXXXXXXX,
router: router,
env: 'production',
triggerEvent: true,
// other options
})
Then use @shershen08 solution in your component
document.addEventListener('yacounterXXXXXXXXinited', () => {
//callback to execute all items from internal array for events
this.$metrika.userParams({
pet: 'cat'
})
//or whatever you want
})
I faced with same problem. If user enable AdBlock or other script remover, i can't call reachGoal(). I get error. I solved this problem with try-catch. Now, it's work perfect.
new Vue({ components: { App }, template: "<App/>", router, data: function () { return { loading: false } }, methods: { **reachGoal: function (goal) { try {this.$metrika.reachGoal(goal)} catch (e) {} }** } }).$mount("#app");
Call in your code:
this.$root.reachGoal('goal')
Add $metrikaEvents:
export default function install (Vue, options = {}) {
updateConfig(options); // Merge options and default config
checkConfig(); // Check if all required options are presented
Vue.prototype.$metrikaEvents = Vue.$metrikaEvents = new Vue();
loadScript(() => { // Load Metrika script
const metrika = createMetrika(Vue) // Create Metrika
startTracking(metrika) // Start autotracking
Vue.$metrikaEvents.$emit('ym:ready', metrika);
}, options.scriptSrc)
}
Listen loadScript
:
mounted() {
this.$metrikaEvents.$on('ym:ready',(metrica) => {
metrica.reachGoal('aim1');
})
},
Add $metrikaEvents:
export default function install (Vue, options = {}) { updateConfig(options); // Merge options and default config checkConfig(); // Check if all required options are presented Vue.prototype.$metrikaEvents = Vue.$metrikaEvents = new Vue(); loadScript(() => { // Load Metrika script const metrika = createMetrika(Vue) // Create Metrika startTracking(metrika) // Start autotracking Vue.$metrikaEvents.$emit('ym:ready', metrika); }, options.scriptSrc) }
Listen
loadScript
:mounted() { this.$metrikaEvents.$on('ym:ready',(metrica) => { metrica.reachGoal('aim1'); }) },
fixed and updated. it works!
Had same issue in Firefox private tab.
Add check before submit goal if this.$metrika
is defined:
if (this.$metrika) this.$metrika.reachGoal('my-goal')
Tried much options, but yacounterXXXXXXXXinited
event not fired..
UPDATE
@armbull Works with env: 'production'
only. Thx!