Files
portal/app/resources/js/plugins/metrika.ts
T
Дмитрий 2bbe2a7612 feat(metrika): Метрика+Вебвизор в линию портала (чтобы выкаты не теряли)
Метрика была потеряна, т.к. клалась мимо конвейера: выкат = git archive HEAD ветки
+ пересборка, а Метрика жила отдельно → перезатёрлась. Кладём в feat/portal-mobile-adaptive
(линию, из которой режутся deploy/*-ветки) → любой будущий выкат несёт её сам.

Загрузчик metrika.ts (только кабинет layout=app), маскировка ПДн лидов
(ym-hide-content/ym-disable-keys) — десктоп-таблица + МОБИЛЬНЫЕ карточки (телефон+
комментарий+aria-label) + канбан + карточка сделки + диалог. Сборка проходит.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 17:00:37 +03:00

60 lines
2.2 KiB
TypeScript

/**
* Ленивый загрузчик Яндекс.Метрики для портала.
* Грузится ТОЛЬКО из роутера при входе в кабинет (meta.layout==='app') — см. router/index.ts.
* id счётчика читается из <meta name="metrika-id"> (проставляется welcome.blade.php по config).
* Вебвизор пишет с маскировкой ПДн (классы ym-hide-content в компонентах кабинета).
*/
declare global {
interface Window {
ym?: (...args: unknown[]) => void;
}
}
let loaded = false;
function counterId(): number | null {
const meta = document.querySelector('meta[name="metrika-id"]');
const raw = meta?.getAttribute('content');
const id = raw ? Number(raw) : NaN;
return Number.isFinite(id) && id > 0 ? id : null;
}
/** Один раз инжектит tag.js и инициализирует Вебвизор. Идемпотентно. No-op без id. */
export function ensureLoaded(): void {
if (loaded) return;
const id = counterId();
if (id === null) return;
loaded = true;
// стандартный bootstrap-стаб ym до загрузки tag.js
const w = window as Window & { ym?: { (...a: unknown[]): void; a?: unknown[]; l?: number } };
w.ym =
w.ym ||
function (...args: unknown[]) {
(w.ym as { a?: unknown[] }).a = (w.ym as { a?: unknown[] }).a || [];
(w.ym as { a: unknown[] }).a.push(args);
};
(w.ym as { l?: number }).l = Number(new Date());
const s = document.createElement('script');
s.async = true;
s.src = `https://mc.yandex.ru/metrika/tag.js?id=${id}`;
document.head.appendChild(s);
// defer:true — без авто-первого-хита; первый хит шлёт роутер вручную
w.ym(id, 'init', {
webvisor: true,
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
defer: true,
});
}
/** Отправить заход (SPA-переход). No-op без id/ym. */
export function hit(url: string): void {
const id = counterId();
if (id === null || typeof window.ym !== 'function') return;
window.ym(id, 'hit', url);
}