feat: useVkMetricGoals
This commit is contained in:
parent
21ee974680
commit
e833fa2aa6
@ -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 =
|
||||
|
30
lib/utils/hooks/useVKMetrics.ts
Normal file
30
lib/utils/hooks/useVKMetrics.ts
Normal file
@ -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]);
|
||||
};
|
61
lib/utils/hooks/useVkMetricGoals.ts
Normal file
61
lib/utils/hooks/useVkMetricGoals.ts
Normal file
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user