Merge pull request 'Add the Top.Mail.Ru counter to all four landings with a lead goal' (#1) from topmail-counter into main

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-09-20 17:47:40 +06:00
8 changed files with 249 additions and 22 deletions
+77 -18
View File
@@ -2,7 +2,10 @@
<html lang="ru"> <html lang="ru">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<title>EXO Recovery Zone для фитнес-клубов | Экзо Групп</title> <title>EXO Recovery Zone для фитнес-клубов | Экзо Групп</title>
<meta <meta
name="description" name="description"
@@ -16,13 +19,22 @@
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:locale" content="ru_RU" /> <meta property="og:locale" content="ru_RU" />
<meta property="og:site_name" content="ЭКЗО Групп" /> <meta property="og:site_name" content="ЭКЗО Групп" />
<meta property="og:title" content="EXO Recovery Zone — восстановление, которое удерживает клиента в клубе" /> <meta
<meta property="og:description" content="3 или 5 аппаратов, дизайн зоны, программы, обучение и." /> property="og:title"
content="EXO Recovery Zone — восстановление, которое удерживает клиента в клубе"
/>
<meta
property="og:description"
content="3 или 5 аппаратов, дизайн зоны, программы, обучение и."
/>
<meta property="og:url" content="%VITE_SITE_URL%" /> <meta property="og:url" content="%VITE_SITE_URL%" />
<meta property="og:image" content="%VITE_SITE_URL%/og-image.webp" /> <meta property="og:image" content="%VITE_SITE_URL%/og-image.webp" />
<meta property="og:image:width" content="1200" /> <meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" /> <meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="EXO Recovery Zone для фитнес-клуба" /> <meta
property="og:image:alt"
content="EXO Recovery Zone для фитнес-клуба"
/>
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<script type="application/ld+json"> <script type="application/ld+json">
@@ -43,37 +55,84 @@
m[i] = m[i] =
m[i] || m[i] ||
function () { function () {
(m[i].a = m[i].a || []).push(arguments) (m[i].a = m[i].a || []).push(arguments);
} };
m[i].l = 1 * new Date() m[i].l = 1 * new Date();
for (var j = 0; j < document.scripts.length; j++) { for (var j = 0; j < document.scripts.length; j++) {
if (document.scripts[j].src === r) { if (document.scripts[j].src === r) {
return return;
} }
} }
k = e.createElement(t) k = e.createElement(t);
a = e.getElementsByTagName(t)[0] a = e.getElementsByTagName(t)[0];
k.async = 1 k.async = 1;
k.src = r k.src = r;
a.parentNode.insertBefore(k, a) a.parentNode.insertBefore(k, a);
})(window, document, 'script', 'https://mc.yandex.ru/metrika/tag.js?id=112352796', 'ym') })(
window,
document,
"script",
"https://mc.yandex.ru/metrika/tag.js?id=112352796",
"ym",
);
ym(112352796, 'init', { ym(112352796, "init", {
ssr: true, ssr: true,
webvisor: true, webvisor: true,
clickmap: true, clickmap: true,
ecommerce: 'dataLayer', ecommerce: "dataLayer",
referrer: document.referrer, referrer: document.referrer,
url: location.href, url: location.href,
accurateTrackBounce: true, accurateTrackBounce: true,
trackLinks: true, trackLinks: true,
}) });
</script> </script>
<!-- /Yandex.Metrika counter --> <!-- /Yandex.Metrika counter -->
<!-- Top.Mail.Ru counter -->
<script type="text/javascript">
var _tmr = window._tmr || (window._tmr = []);
_tmr.push({
id: "3795059",
type: "pageView",
start: new Date().getTime(),
});
(function (d, w, id) {
if (d.getElementById(id)) return;
var ts = d.createElement("script");
ts.type = "text/javascript";
ts.async = true;
ts.id = id;
ts.src = "https://top-fwz1.mail.ru/js/code.js";
var f = function () {
var s = d.getElementsByTagName("script")[0];
s.parentNode.insertBefore(ts, s);
};
if (w.opera == "[object Opera]") {
d.addEventListener("DOMContentLoaded", f, false);
} else {
f();
}
})(document, window, "tmr-code");
</script>
<!-- /Top.Mail.Ru counter -->
</head> </head>
<body> <body>
<noscript <noscript
><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div ><div>
<img
src="https://mc.yandex.ru/watch/112352796"
style="position: absolute; left: -9999px"
alt=""
/></div
></noscript>
<noscript
><div>
<img
src="https://top-fwz1.mail.ru/counter?id=3795059;js=na"
style="position: absolute; left: -9999px"
alt="Top.Mail.Ru"
/></div
></noscript> ></noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
+22 -1
View File
@@ -12,6 +12,9 @@ const DRAFT_KEY = 'exo_fitness_lead_draft'
/** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */ /** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */
const METRIKA_ID = 112352796 const METRIKA_ID = 112352796
/** Счётчик Top.Mail.Ru — тот же, что в инлайн-снипете index.html. */
const TMR_ID = '3795059'
/** Query-string UTM tags, forwarded to amoCRM with the lead. */ /** Query-string UTM tags, forwarded to amoCRM with the lead. */
function collectUtm(): Record<string, string> { function collectUtm(): Record<string, string> {
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)
@@ -63,7 +66,10 @@ export async function submitLead(form: LeadFormId, values: Omit<LeadInput, 'form
window.dataLayer = window.dataLayer ?? [] window.dataLayer = window.dataLayer ?? []
window.dataLayer.push({ event: 'fitness_lead_sent', form, configuration: values.configuration }) window.dataLayer.push({ event: 'fitness_lead_sent', form, configuration: values.configuration })
// leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже. // leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже.
if (body.leadId !== 0) reachGoal('FORM_SUCCESS') if (body.leadId !== 0) {
reachGoal('FORM_SUCCESS')
tmrReachGoal('form')
}
localStorage.removeItem(DRAFT_KEY) localStorage.removeItem(DRAFT_KEY)
return { ok: true } return { ok: true }
} catch (error) { } catch (error) {
@@ -99,6 +105,20 @@ function reachGoal(goal: string) {
} }
} }
/**
* Цель Top.Mail.Ru. `_tmr` — обычная очередь-массив: пуши, сделанные до загрузки
* code.js, счётчик разбирает сам, поэтому ждать загрузку не нужно.
*/
function tmrReachGoal(goal: string) {
try {
window._tmr = window._tmr ?? []
window._tmr.push({ type: 'reachGoal', id: TMR_ID, goal })
} catch (error) {
// Аналитика не имеет права ломать отправку формы.
console.warn('Top.Mail.Ru reachGoal failed', error)
}
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Клик по кнопке звонка */ /* Клик по кнопке звонка */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -173,5 +193,6 @@ declare global {
interface Window { interface Window {
dataLayer?: Record<string, unknown>[] dataLayer?: Record<string, unknown>[]
ym?: (counterId: number, action: string, ...args: unknown[]) => void ym?: (counterId: number, action: string, ...args: unknown[]) => void
_tmr?: Record<string, unknown>[]
} }
} }
+28
View File
@@ -74,11 +74,39 @@
}) })
</script> </script>
<!-- /Yandex.Metrika counter --> <!-- /Yandex.Metrika counter -->
<!-- Top.Mail.Ru counter -->
<script type="text/javascript">
var _tmr = window._tmr || (window._tmr = [])
_tmr.push({ id: '3795059', type: 'pageView', start: new Date().getTime() })
;(function (d, w, id) {
if (d.getElementById(id)) return
var ts = d.createElement('script')
ts.type = 'text/javascript'
ts.async = true
ts.id = id
ts.src = 'https://top-fwz1.mail.ru/js/code.js'
var f = function () {
var s = d.getElementsByTagName('script')[0]
s.parentNode.insertBefore(ts, s)
}
if (w.opera == '[object Opera]') {
d.addEventListener('DOMContentLoaded', f, false)
} else {
f()
}
})(document, window, 'tmr-code')
</script>
<!-- /Top.Mail.Ru counter -->
</head> </head>
<body> <body>
<noscript <noscript
><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div ><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div
></noscript> ></noscript>
<noscript
><div>
<img src="https://top-fwz1.mail.ru/counter?id=3795059;js=na" style="position: absolute; left: -9999px" alt="Top.Mail.Ru" /></div
></noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
+22 -1
View File
@@ -12,6 +12,9 @@ const DRAFT_KEY = 'exo_hotel_lead_draft'
/** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */ /** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */
const METRIKA_ID = 112352796 const METRIKA_ID = 112352796
/** Счётчик Top.Mail.Ru — тот же, что в инлайн-снипете index.html. */
const TMR_ID = '3795059'
/** Query-string UTM tags, forwarded to amoCRM with the lead. */ /** Query-string UTM tags, forwarded to amoCRM with the lead. */
function collectUtm(): Record<string, string> { function collectUtm(): Record<string, string> {
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)
@@ -66,7 +69,10 @@ export async function submitLead(
window.dataLayer = window.dataLayer ?? [] window.dataLayer = window.dataLayer ?? []
window.dataLayer.push({ event: 'hotel_lead_sent', form }) window.dataLayer.push({ event: 'hotel_lead_sent', form })
// leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже. // leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже.
if (body.leadId !== 0) reachGoal('FORM_SUCCESS') if (body.leadId !== 0) {
reachGoal('FORM_SUCCESS')
tmrReachGoal('form')
}
localStorage.removeItem(DRAFT_KEY) localStorage.removeItem(DRAFT_KEY)
return { ok: true } return { ok: true }
} catch (error) { } catch (error) {
@@ -102,6 +108,20 @@ function reachGoal(goal: string) {
} }
} }
/**
* Цель Top.Mail.Ru. `_tmr` — обычная очередь-массив: пуши, сделанные до загрузки
* code.js, счётчик разбирает сам, поэтому ждать загрузку не нужно.
*/
function tmrReachGoal(goal: string) {
try {
window._tmr = window._tmr ?? []
window._tmr.push({ type: 'reachGoal', id: TMR_ID, goal })
} catch (error) {
// Аналитика не имеет права ломать отправку формы.
console.warn('Top.Mail.Ru reachGoal failed', error)
}
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Клик по кнопке звонка */ /* Клик по кнопке звонка */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -176,5 +196,6 @@ declare global {
interface Window { interface Window {
dataLayer?: Record<string, unknown>[] dataLayer?: Record<string, unknown>[]
ym?: (counterId: number, action: string, ...args: unknown[]) => void ym?: (counterId: number, action: string, ...args: unknown[]) => void
_tmr?: Record<string, unknown>[]
} }
} }
+28
View File
@@ -73,11 +73,39 @@
}) })
</script> </script>
<!-- /Yandex.Metrika counter --> <!-- /Yandex.Metrika counter -->
<!-- Top.Mail.Ru counter -->
<script type="text/javascript">
var _tmr = window._tmr || (window._tmr = [])
_tmr.push({ id: '3795059', type: 'pageView', start: new Date().getTime() })
;(function (d, w, id) {
if (d.getElementById(id)) return
var ts = d.createElement('script')
ts.type = 'text/javascript'
ts.async = true
ts.id = id
ts.src = 'https://top-fwz1.mail.ru/js/code.js'
var f = function () {
var s = d.getElementsByTagName('script')[0]
s.parentNode.insertBefore(ts, s)
}
if (w.opera == '[object Opera]') {
d.addEventListener('DOMContentLoaded', f, false)
} else {
f()
}
})(document, window, 'tmr-code')
</script>
<!-- /Top.Mail.Ru counter -->
</head> </head>
<body> <body>
<noscript <noscript
><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div ><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div
></noscript> ></noscript>
<noscript
><div>
<img src="https://top-fwz1.mail.ru/counter?id=3795059;js=na" style="position: absolute; left: -9999px" alt="Top.Mail.Ru" /></div
></noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
+22 -1
View File
@@ -12,6 +12,9 @@ const DRAFT_KEY = 'exo_medcenter_lead_draft'
/** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */ /** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */
const METRIKA_ID = 112352796 const METRIKA_ID = 112352796
/** Счётчик Top.Mail.Ru — тот же, что в инлайн-снипете index.html. */
const TMR_ID = '3795059'
const FALLBACK_ERROR = const FALLBACK_ERROR =
'Не удалось отправить форму автоматически. Данные сохранены в браузере — свяжитесь с нами по +7 927 789-60-71.' 'Не удалось отправить форму автоматически. Данные сохранены в браузере — свяжитесь с нами по +7 927 789-60-71.'
@@ -66,7 +69,10 @@ export async function submitLead(
window.dataLayer = window.dataLayer ?? [] window.dataLayer = window.dataLayer ?? []
window.dataLayer.push({ event: 'medcenter_lead_sent', form }) window.dataLayer.push({ event: 'medcenter_lead_sent', form })
// leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже. // leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже.
if (body.leadId !== 0) reachGoal('FORM_SUCCESS') if (body.leadId !== 0) {
reachGoal('FORM_SUCCESS')
tmrReachGoal('form')
}
localStorage.removeItem(DRAFT_KEY) localStorage.removeItem(DRAFT_KEY)
return { ok: true } return { ok: true }
} catch (error) { } catch (error) {
@@ -98,6 +104,20 @@ function reachGoal(goal: string) {
} }
} }
/**
* Цель Top.Mail.Ru. `_tmr` — обычная очередь-массив: пуши, сделанные до загрузки
* code.js, счётчик разбирает сам, поэтому ждать загрузку не нужно.
*/
function tmrReachGoal(goal: string) {
try {
window._tmr = window._tmr ?? []
window._tmr.push({ type: 'reachGoal', id: TMR_ID, goal })
} catch (error) {
// Аналитика не имеет права ломать отправку формы.
console.warn('Top.Mail.Ru reachGoal failed', error)
}
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Клик по кнопке звонка */ /* Клик по кнопке звонка */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -172,5 +192,6 @@ declare global {
interface Window { interface Window {
dataLayer?: Record<string, unknown>[] dataLayer?: Record<string, unknown>[]
ym?: (counterId: number, action: string, ...args: unknown[]) => void ym?: (counterId: number, action: string, ...args: unknown[]) => void
_tmr?: Record<string, unknown>[]
} }
} }
+28
View File
@@ -73,11 +73,39 @@
}) })
</script> </script>
<!-- /Yandex.Metrika counter --> <!-- /Yandex.Metrika counter -->
<!-- Top.Mail.Ru counter -->
<script type="text/javascript">
var _tmr = window._tmr || (window._tmr = [])
_tmr.push({ id: '3795059', type: 'pageView', start: new Date().getTime() })
;(function (d, w, id) {
if (d.getElementById(id)) return
var ts = d.createElement('script')
ts.type = 'text/javascript'
ts.async = true
ts.id = id
ts.src = 'https://top-fwz1.mail.ru/js/code.js'
var f = function () {
var s = d.getElementsByTagName('script')[0]
s.parentNode.insertBefore(ts, s)
}
if (w.opera == '[object Opera]') {
d.addEventListener('DOMContentLoaded', f, false)
} else {
f()
}
})(document, window, 'tmr-code')
</script>
<!-- /Top.Mail.Ru counter -->
</head> </head>
<body> <body>
<noscript <noscript
><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div ><div><img src="https://mc.yandex.ru/watch/112352796" style="position: absolute; left: -9999px" alt="" /></div
></noscript> ></noscript>
<noscript
><div>
<img src="https://top-fwz1.mail.ru/counter?id=3795059;js=na" style="position: absolute; left: -9999px" alt="Top.Mail.Ru" /></div
></noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
+22 -1
View File
@@ -12,6 +12,9 @@ const DRAFT_KEY = 'exo_medcenter_no_physio_lead_draft'
/** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */ /** Тот же счётчик, что и в инлайн-снипете index.html — один на все четыре лендинга. */
const METRIKA_ID = 112352796 const METRIKA_ID = 112352796
/** Счётчик Top.Mail.Ru — тот же, что в инлайн-снипете index.html. */
const TMR_ID = '3795059'
const FALLBACK_ERROR = const FALLBACK_ERROR =
'Не удалось отправить форму автоматически. Данные сохранены в браузере — свяжитесь с нами по +7 927 789-60-71.' 'Не удалось отправить форму автоматически. Данные сохранены в браузере — свяжитесь с нами по +7 927 789-60-71.'
@@ -66,7 +69,10 @@ export async function submitLead(
window.dataLayer = window.dataLayer ?? [] window.dataLayer = window.dataLayer ?? []
window.dataLayer.push({ event: 'medcenter_no_physio_lead_sent', form }) window.dataLayer.push({ event: 'medcenter_no_physio_lead_sent', form })
// leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже. // leadId === 0 — ответ-обманка ханипота: сделки в amoCRM нет, конверсии тоже.
if (body.leadId !== 0) reachGoal('FORM_SUCCESS') if (body.leadId !== 0) {
reachGoal('FORM_SUCCESS')
tmrReachGoal('form')
}
localStorage.removeItem(DRAFT_KEY) localStorage.removeItem(DRAFT_KEY)
return { ok: true } return { ok: true }
} catch (error) { } catch (error) {
@@ -98,6 +104,20 @@ function reachGoal(goal: string) {
} }
} }
/**
* Цель Top.Mail.Ru. `_tmr` — обычная очередь-массив: пуши, сделанные до загрузки
* code.js, счётчик разбирает сам, поэтому ждать загрузку не нужно.
*/
function tmrReachGoal(goal: string) {
try {
window._tmr = window._tmr ?? []
window._tmr.push({ type: 'reachGoal', id: TMR_ID, goal })
} catch (error) {
// Аналитика не имеет права ломать отправку формы.
console.warn('Top.Mail.Ru reachGoal failed', error)
}
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Клик по кнопке звонка */ /* Клик по кнопке звонка */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
@@ -172,5 +192,6 @@ declare global {
interface Window { interface Window {
dataLayer?: Record<string, unknown>[] dataLayer?: Record<string, unknown>[]
ym?: (counterId: number, action: string, ...args: unknown[]) => void ym?: (counterId: number, action: string, ...args: unknown[]) => void
_tmr?: Record<string, unknown>[]
} }
} }