feat: useVkMetricGoals

This commit is contained in:
IlyaDoronin 2024-04-22 17:13:43 +03:00
parent 21ee974680
commit e833fa2aa6
6 changed files with 187 additions and 91 deletions

@ -15,6 +15,7 @@ import NextButton from "./tools/NextButton";
import PrevButton from "./tools/PrevButton";
import QuestionSelect from "./QuestionSelect";
import { useYandexMetrics } from "@/utils/hooks/useYandexMetrics";
import { useVKMetrics } from "@/utils/hooks/useVKMetrics";
export default function ViewPublicationPage() {
const {
@ -37,6 +38,7 @@ export default function ViewPublicationPage() {
setQuestion,
} = useQuestionFlowControl();
useYandexMetrics(settings?.cfg?.yandexMetricNumber);
useVKMetrics(settings?.cfg?.vkMetricNumber);
const isAnswer = answers.some(
(ans) => ans.questionId === currentQuestion?.id

@ -13,104 +13,104 @@ import { useState } from "react";
import { useQuizViewStore } from "@/stores/quizView";
type DateProps = {
currentQuestion: QuizQuestionDate;
currentQuestion: QuizQuestionDate;
};
export const Date = ({ currentQuestion }: DateProps) => {
const theme = useTheme();
const { settings, quizId, preview } = useQuizData();
const answers = useQuizViewStore(state => state.answers);
const updateAnswer = useQuizViewStore(state => state.updateAnswer);
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const currentAnswer = moment(answer) || moment();
const [isSending, setIsSending] = useState<boolean>(false);
const theme = useTheme();
const { settings, quizId, preview } = useQuizData();
const answers = useQuizViewStore((state) => state.answers);
const updateAnswer = useQuizViewStore((state) => state.updateAnswer);
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const currentAnswer = moment(answer) || moment();
const [isSending, setIsSending] = useState<boolean>(false);
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
{currentQuestion.title}
</Typography>
<Box
return (
<Box>
<Typography
variant="h5"
color={theme.palette.text.primary}
sx={{ wordBreak: "break-word" }}
>
{currentQuestion.title}
</Typography>
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
marginTop: "20px",
}}
>
<DatePicker
format="DD/MM/YYYY"
slots={{
openPickerIcon: () => (
<CalendarIcon
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
marginTop: "20px",
"& path": { stroke: theme.palette.primary.main },
"& rect": { stroke: theme.palette.primary.main },
}}
>
<DatePicker
format="DD/MM/YYYY"
slots={{
openPickerIcon: () => (
<CalendarIcon
sx={{
"& path": { stroke: theme.palette.primary.main },
"& rect": { stroke: theme.palette.primary.main },
}}
/>
),
}}
value={currentAnswer}
onChange={async (date) => {
if (isSending || !date) return;
/>
),
}}
value={currentAnswer}
onChange={async (date) => {
if (isSending || !date) return;
setIsSending(true);
try {
await sendAnswer({
questionId: currentQuestion.id,
body: moment(date).format("YYYY.MM.DD"),
qid: quizId,
preview
});
setIsSending(true);
try {
await sendAnswer({
questionId: currentQuestion.id,
body: moment(date).format("YYYY.MM.DD"),
qid: quizId,
preview,
});
updateAnswer(currentQuestion.id, date, 0);
} catch (e) {
enqueueSnackbar("ответ не был засчитан");
}
updateAnswer(currentQuestion.id, date, 0);
} catch (e) {
enqueueSnackbar("ответ не был засчитан");
}
setIsSending(false);
}}
slotProps={{
openPickerButton: {
sx: {
p: 0,
},
"data-cy": "open-datepicker",
},
layout: {
sx: { backgroundColor: theme.palette.background.default },
},
}}
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": {
py: "11px",
pl: "20px",
lineHeight: "19px",
},
"& fieldset": {
borderColor: "#9A9AAF",
},
},
}}
/>
</Box>
</Box>
);
setIsSending(false);
}}
slotProps={{
openPickerButton: {
sx: {
p: 0,
},
"data-cy": "open-datepicker",
},
layout: {
sx: { backgroundColor: theme.palette.background.default },
},
}}
sx={{
"& .MuiInputBase-root": {
backgroundColor: settings.cfg.design
? quizThemes[settings.cfg.theme].isLight
? "#F2F3F7"
: "rgba(154,154,175, 0.2)"
: quizThemes[settings.cfg.theme].isLight
? "white"
: theme.palette.background.default,
borderRadius: "10px",
maxWidth: "250px",
pr: "30px",
"& input": {
py: "11px",
pl: "20px",
lineHeight: "19px",
},
"& fieldset": {
borderColor: "#9A9AAF",
},
},
}}
/>
</Box>
</Box>
);
};

@ -109,6 +109,7 @@ export interface QuizConfig {
};
meta: string;
yandexMetricNumber: number | undefined;
vkMetricNumber: number | undefined;
}
export type FormContactFieldName =

@ -0,0 +1,30 @@
import { useEffect } from "react";
export const useVKMetrics = (vkMetricNumber: number | undefined) => {
useEffect(() => {
if (
vkMetricNumber &&
typeof vkMetricNumber === "number" &&
!Number.isNaN(vkMetricNumber)
) {
const script = document.createElement("script");
script.type = "text/javascript";
script.innerHTML = `
var _tmr = window._tmr || (window._tmr = []);
_tmr.push({id: "${vkMetricNumber}", 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");
`;
document.body.appendChild(script);
const noscript = document.createElement("noscript");
noscript.innerHTML = `<div><img src="https://top-fwz1.mail.ru/counter?id=${vkMetricNumber};js=na" style="position:absolute;left:-9999px;" alt="Top.Mail.Ru" /></div>`;
document.body.appendChild(noscript);
}
}, [vkMetricNumber]);
};

@ -0,0 +1,61 @@
import { useEffect, useState } from "react";
type VkMetric = {
type: "reachGoal";
id: number;
goal: string;
};
type ExtendedWindow = Window & { _tmp?: VkMetric[] };
type Messenger =
| "telegram"
| "viber"
| "whatsapp"
| "vkontakte"
| "messenger"
| "skype"
| "instagram";
const sendMetrics = (vkPixelId: number | undefined, goal: string) => {
if (vkPixelId) {
(window as ExtendedWindow)._tmp?.push({
type: "reachGoal",
id: vkPixelId,
goal,
});
}
};
export const useVkMetricGoals = (vkPixelId: number | undefined) => {
const [vkId, setVkId] = useState<number | undefined>(undefined);
useEffect(() => {
if (vkPixelId) {
setVkId(vkPixelId);
}
}, [vkPixelId]);
return {
// Посетитель открыл квиз
quizOpened: () => sendMetrics(vkId, "penaquiz-start"),
// Посетитель нажал на кнопку стартовой страницы
firstPageOpened: () => sendMetrics(vkId, "penaquiz-startquiz"),
// Посетитель кликнул по номеру телефона на стартовой странице
phoneNumberOpened: () => sendMetrics(vkId, "penaquiz-phone"),
// Посетитель кликнул по email на стартовой странице
emailOpened: () => sendMetrics(vkId, "penaquiz-email"),
// Посетитель увидел определенный результат (id - айдишник вопроса с типом result)
resultShown: (resultId: string) => sendMetrics(vkId, `penaquiz-result-${resultId}`),
// Посетитель дошёл до формы контактов
contactsFormOpened: () => sendMetrics(vkId, "penaquiz-form"),
// Посетитель заполнил форму контактов
contactsFormFilled: () => sendMetrics(vkId, "penaquiz-contacts"),
// Посетитель отправил заявку с мессенджером
messengerRequestSended: (messenger: Messenger) =>
sendMetrics(vkId, `marquiz-messengers-${messenger}`),
// Посетитель прошёл вопрос
questionPassed: (questionId: string) =>
sendMetrics(vkId, `marquiz-step${questionId}`),
};
};

@ -3,6 +3,7 @@ import { useEffect } from "react";
export const useYandexMetrics = (yandexMetricNumber: number | undefined) => {
useEffect(() => {
if (
yandexMetricNumber &&
typeof yandexMetricNumber === "number" &&
!Number.isNaN(yandexMetricNumber)
) {
@ -22,6 +23,7 @@ export const useYandexMetrics = (yandexMetricNumber: number | undefined) => {
webvisor:true
});
`;
document.body.appendChild(script);
const noscript = document.createElement("noscript");