Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$metrika is undefined #10

Open
andrei2424 opened this issue Nov 8, 2018 · 10 comments
Open

$metrika is undefined #10

andrei2424 opened this issue Nov 8, 2018 · 10 comments

Comments

@andrei2424
Copy link

Hey.

  • vue-yandex-metrika version: 1.7.2
  • node version: 10.13.0
  • npm (or yarn) 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/

@picarsite
Copy link

picarsite commented Apr 21, 2019

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.

@shershen08
Copy link
Contributor

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

@picarsite
Copy link

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 :)

@shershen08
Copy link
Contributor

shershen08 commented May 1, 2019

@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:

  1. create internal array for events that were called by the consumer while YM was not operating
  2. add triggerEvent: true in config https://github.com/vchaptsev/vue-yandex-metrika/blob/master/src/config.js#L14
  3. add to init code
document.addEventListener('yacounter${this.config.id}inited', () => {
  //callback to execute all items from internal array for events 
});

@veebull
Copy link

veebull commented Oct 19, 2019

@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:

  1. create internal array for events that were called by the consumer while YM was not operating
  2. add triggerEvent: true in config https://github.com/vchaptsev/vue-yandex-metrika/blob/master/src/config.js#L14
  3. 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 image

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
})

@Workoverflow
Copy link

Workoverflow commented Jan 16, 2020

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')

@iafilin
Copy link

iafilin commented Feb 21, 2020

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');
            })
        },

@iafilin
Copy link

iafilin commented Feb 21, 2020

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!

@pdapnz
Copy link

pdapnz commented Sep 30, 2020

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')

@Sogl
Copy link

Sogl commented Jun 3, 2023

Tried much options, but yacounterXXXXXXXXinited event not fired..

UPDATE

@armbull Works with env: 'production' only. Thx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants