Skip to content

Commit 2e0aa13

Browse files
authored
Merge pull request #24 from zirreal/main
added new popup display + vk
2 parents fbd88df + f0cf7cf commit 2e0aa13

File tree

3 files changed

+141
-9
lines changed

3 files changed

+141
-9
lines changed

src/components/CookieConsent.astro

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@ const COOKIE_AGREED_KEY = 'cookieAgreed';
2222

2323
const hasConsented = (): boolean => localStorage.getItem(COOKIE_AGREED_KEY) === 'true';
2424
let yandexInitialized = false;
25+
let mailruInitialized = false;
2526

2627
declare global {
27-
interface Window { ym?: (...args: any[]) => void; }
28+
interface Window {
29+
ym?: (...args: any[]) => void;
30+
_tmr?: any[];
31+
}
2832
}
2933

34+
// YANDEX
35+
3036
const addNoscriptPixel = (): void => {
3137
const img = document.createElement('img');
3238
img.src = 'https://mc.yandex.ru/watch/103487153';
@@ -50,7 +56,7 @@ const yandexMetrika = (): void => {
5056

5157
if ([...e.scripts].some(script => script.src === r)) return;
5258

53-
const k = e.createElement(t);
59+
const k = e.createElement(t) as HTMLScriptElement;
5460
const a = e.getElementsByTagName(t)[0];
5561
k.async = true;
5662
k.src = r;
@@ -66,6 +72,44 @@ const yandexMetrika = (): void => {
6672
});
6773
};
6874

75+
76+
// MAIL
77+
78+
const addMailruNoscriptPixel = (): void => {
79+
const img = document.createElement('img');
80+
img.src = 'https://top-fwz1.mail.ru/counter?id=3709261;js=na';
81+
img.style.position = 'absolute';
82+
img.style.left = '-9999px';
83+
img.alt = 'Top.Mail.Ru';
84+
const div = document.createElement('div');
85+
div.appendChild(img);
86+
document.body.appendChild(div);
87+
};
88+
89+
const mailruCounter = (): void => {
90+
if (!hasConsented() || mailruInitialized) return;
91+
mailruInitialized = true;
92+
addMailruNoscriptPixel();
93+
94+
window._tmr = window._tmr || [];
95+
window._tmr.push({ id: '3709261', type: 'pageView', start: new Date().getTime() });
96+
97+
(function (d, w, id) {
98+
if (d.getElementById(id)) return;
99+
const ts = d.createElement('script');
100+
ts.type = 'text/javascript';
101+
ts.async = true;
102+
ts.id = id;
103+
ts.src = 'https://top-fwz1.mail.ru/js/code.js';
104+
const f = function () {
105+
const s = d.getElementsByTagName('script')[0];
106+
s?.parentNode?.insertBefore(ts, s);
107+
};
108+
if ((w as any).opera === '[object Opera]') d.addEventListener('DOMContentLoaded', f, false);
109+
else f();
110+
})(document, window, 'tmr-code');
111+
};
112+
69113
const preventInteraction = (e: Event) => e.preventDefault();
70114
const preventTabNavigation = (e: KeyboardEvent) => {
71115
if (e.key === 'Tab') e.preventDefault();
@@ -87,6 +131,7 @@ cookieButton?.addEventListener('click', () => {
87131
overlay?.classList.remove('active');
88132
localStorage.setItem(COOKIE_AGREED_KEY, 'true');
89133
yandexMetrika();
134+
mailruCounter();
90135

91136
document.body.style.overflow = '';
92137
document.removeEventListener('keydown', preventTabNavigation, { capture: true });
@@ -97,6 +142,7 @@ cookieButton?.addEventListener('click', () => {
97142
document.addEventListener('DOMContentLoaded', () => {
98143
if (hasConsented()) {
99144
yandexMetrika();
145+
mailruCounter();
100146
}
101147
});
102148
</script>

src/layouts/Layout.astro

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,16 @@ import '../assets/styles/main.css';
6161
<meta name="twitter:image" content={ogImage}>
6262
</head>
6363
<body transition:animate="fade" class:list={[{dark: isDark}]}>
64-
<main class="main">
65-
<Header client:load/>
66-
<slot />
67-
<Footer/>
68-
</main>
64+
<main class="main">
65+
<Header client:load/>
66+
<slot />
67+
<Footer/>
68+
</main>
6969

70-
<CookieConsent/>
71-
<FormPopup client:load/>
70+
<CookieConsent/>
71+
<FormPopup client:load/>
7272
</body>
73+
7374
</html>
7475

7576
<script>

src/pages/index.astro

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,91 @@ import WORKDECOR from '../assets/img/work-decor.webp';
306306

307307
</Layout>
308308

309+
<script>
310+
document.addEventListener('DOMContentLoaded', () => {
311+
const section = document.querySelector<HTMLElement>('#features');
312+
if (!section) return;
313+
314+
let timerId: number | null = null;
315+
let hasTriggered = false;
316+
317+
const startTimer = () => {
318+
if (hasTriggered || timerId) return;
319+
timerId = window.setTimeout(triggerPopup, 3000) ;
320+
};
321+
322+
const cancelTimer = () => {
323+
if (timerId) {
324+
clearTimeout(timerId);
325+
timerId = null;
326+
}
327+
};
328+
329+
const triggerPopup = () => {
330+
if (hasTriggered) return;
331+
hasTriggered = true;
332+
333+
window.dispatchEvent(new CustomEvent('open-contact-popup'));
334+
335+
cancelTimer();
336+
observer.disconnect();
337+
window.removeEventListener('scroll', onScroll);
338+
window.removeEventListener('resize', onResize);
339+
window.removeEventListener('visibilitychange', onVisibilityChange);
340+
window.removeEventListener('hashchange', onHashChange);
341+
};
342+
343+
344+
const debounce = <T extends (...args: any[]) => void>(fn: T, wait: number) => {
345+
let timeout: number | null = null;
346+
return (...args: Parameters<T>) => {
347+
if (timeout) clearTimeout(timeout);
348+
timeout = window.setTimeout(() => fn(...args), wait);
349+
};
350+
};
351+
352+
const onScrollEnd = debounce(() => {
353+
const rect = section.getBoundingClientRect();
354+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
355+
const near = !(rect.bottom < -200 || rect.top > viewportHeight + 200);
356+
357+
if (near) startTimer();
358+
else cancelTimer();
359+
}, 150);
360+
361+
const onScroll = () => onScrollEnd();
362+
const onResize = () => onScrollEnd();
363+
const onVisibilityChange = () => {
364+
if (document.hidden) cancelTimer();
365+
else onScrollEnd();
366+
};
367+
const onHashChange = () => {
368+
cancelTimer();
369+
onScrollEnd();
370+
};
371+
372+
const observer = new IntersectionObserver(
373+
(entries) => {
374+
const entry = entries[0];
375+
if (entry.isIntersecting && !hasTriggered) startTimer();
376+
else cancelTimer();
377+
},
378+
{ threshold: 0.0, rootMargin: '400px 0px 400px 0px' }
379+
);
380+
381+
observer.observe(section);
382+
window.addEventListener('scroll', onScroll, { passive: true });
383+
window.addEventListener('resize', onResize);
384+
window.addEventListener('visibilitychange', onVisibilityChange);
385+
window.addEventListener('hashchange', onHashChange);
386+
387+
onScrollEnd();
388+
});
389+
390+
</script>
391+
392+
393+
309394
<style is:global>
310395
.home-page-cases .swiper {
311396
margin-bottom: var(--space);

0 commit comments

Comments
 (0)