Open Aleks-developer opened 5 years ago
@Aleks-developer Я поковырялся в коде, и нашёл решение - инициализатор надо импортировать как функцию в index.js - и запускать с 3 агрументами
import YMInitializer from 'react-yandex-metrika/lib/init'
YMInitializer([yandexMetrikaKey], { webvisor: true }, '2')
самое главное запускать эту функцию до самого кода реакта
а дальше в онкликах и роутах можно использовать ym как в документации
@JustFly1984 Так не работает, так как даже нет никакой сетевой активности
Well, at the end I wrote my own script:
const isBrowser = typeof document !== 'undefined'
export const injectScript = ({ url, id, onSuccess, onError }) => {
if (isBrowser) {
return new Promise((resolve, reject) => {
const prevScript = document.getElementById(id)
if (!prevScript) {
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = url
script.id = id
script.async = true
script.onload = () => {
resolve(onSuccess())
}
script.onerror = (e) => {
reject(onError(e))
}
document.head.appendChild(script)
} else {
resolve(onSuccess())
}
})
} else {
onError()
}
}
export const init = id => {
try {
window[`yaCounter${id}`] = new Ya['Metrika2']({
id,
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
})
} catch (err) {
console.warn(err)
}
}
export const ym = (id, methodName, ...args) => {
if (
isBrowser &&
typeof window[`yaCounter${id}`] !== 'undefined'
) {
window[`yaCounter${id}`][methodName](...args)
}
}
export const injectYm = id => {
injectScript({
id,
url: 'https://mc.yandex.ru/metrika/tag.js',
onSuccess: () => {
init(id)
ym(id, 'hit', window.location.pathname)
console.log('yandex metrika initialized')
},
onError: () => {
console.error('Yandex metrika if failed')
}
})
}
You need to injectYm('546346)
before ReactDOM.render, and use ym(546346, 'hit', window.location.pathname)
Still no news?
Отправил PR, который должен исправить этот баг. Примите, пожалуйста.
Ошибка возникает, если в коде ym()
вызывается раньше, чем примонтировался <YMInitializer/>
.
Да, так и есть. Опишу свой сценарий использования более подробно.
У меня YMInitializer
подключается как в документации:
<YMInitializer accounts={[YANDEX_METRIKA_ID]} options={{ defer: true }} />
а ym()
вызывается в коде middleware/saga при смене пути. Когда загружается первая страница, происходит первое событие LOCATION_CHANGE
. Но в этот момент YMInitializer
ещё не смонтирован.
Я нашёл ещё один способ обойти этот баг. Он не требует внесения изменений в библиотеку, и события не должны теряться.
import {
call, all, takeLatest, delay
} from 'redux-saga/effects';
import { LOCATION_CHANGE } from 'connected-react-router';
import ym from 'react-yandex-metrika';
function* locationChangeSaga({ payload }) {
try {
// Событие роутера LOCATION_CHANGE прилетает раньше, чем успевает отработать YMInitializer.
// Поэтому для hit-событий добавляем небольшую задержку.
yield delay(100);
yield call(ym, 'hit', payload.location.pathname);
} catch (error) {
logServerError(error);
}
}
export default function* rootSaga() {
yield all([
yield takeLatest(LOCATION_CHANGE, locationChangeSaga)
]);
}
У меня никак не работает JavaScript событие, <YMInitializer accounts={[66898726]} options={{webvisor: true}} version="2" />
ym('hit', '/'); ym(66898726,'reachGoal','arhitektor-form');
что интересно это то что в дебаге hit видно в консоле а вот reachGoal ну никак нет метрика тоже работает только цели никак не отоброжаются
Здравствуйте. Делаю все по инструкции, после добавления ym на событие onClick вылазит следующая ошибка: TypeError: Cannot read property 'forEach' of undefined. В чем может быть проблема?