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 PrevButton from "./tools/PrevButton";
|
||||||
import QuestionSelect from "./QuestionSelect";
|
import QuestionSelect from "./QuestionSelect";
|
||||||
import { useYandexMetrics } from "@/utils/hooks/useYandexMetrics";
|
import { useYandexMetrics } from "@/utils/hooks/useYandexMetrics";
|
||||||
|
import { useVKMetrics } from "@/utils/hooks/useVKMetrics";
|
||||||
|
|
||||||
export default function ViewPublicationPage() {
|
export default function ViewPublicationPage() {
|
||||||
const {
|
const {
|
||||||
@ -37,6 +38,7 @@ export default function ViewPublicationPage() {
|
|||||||
setQuestion,
|
setQuestion,
|
||||||
} = useQuestionFlowControl();
|
} = useQuestionFlowControl();
|
||||||
useYandexMetrics(settings?.cfg?.yandexMetricNumber);
|
useYandexMetrics(settings?.cfg?.yandexMetricNumber);
|
||||||
|
useVKMetrics(settings?.cfg?.vkMetricNumber);
|
||||||
|
|
||||||
const isAnswer = answers.some(
|
const isAnswer = answers.some(
|
||||||
(ans) => ans.questionId === currentQuestion?.id
|
(ans) => ans.questionId === currentQuestion?.id
|
||||||
|
@ -13,104 +13,104 @@ import { useState } from "react";
|
|||||||
import { useQuizViewStore } from "@/stores/quizView";
|
import { useQuizViewStore } from "@/stores/quizView";
|
||||||
|
|
||||||
type DateProps = {
|
type DateProps = {
|
||||||
currentQuestion: QuizQuestionDate;
|
currentQuestion: QuizQuestionDate;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Date = ({ currentQuestion }: DateProps) => {
|
export const Date = ({ currentQuestion }: DateProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { settings, quizId, preview } = useQuizData();
|
const { settings, quizId, preview } = useQuizData();
|
||||||
const answers = useQuizViewStore(state => state.answers);
|
const answers = useQuizViewStore((state) => state.answers);
|
||||||
const updateAnswer = useQuizViewStore(state => state.updateAnswer);
|
const updateAnswer = useQuizViewStore((state) => state.updateAnswer);
|
||||||
const answer = answers.find(
|
const answer = answers.find(
|
||||||
({ questionId }) => questionId === currentQuestion.id
|
({ questionId }) => questionId === currentQuestion.id
|
||||||
)?.answer as string;
|
)?.answer as string;
|
||||||
const currentAnswer = moment(answer) || moment();
|
const currentAnswer = moment(answer) || moment();
|
||||||
const [isSending, setIsSending] = useState<boolean>(false);
|
const [isSending, setIsSending] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h5"
|
variant="h5"
|
||||||
color={theme.palette.text.primary}
|
color={theme.palette.text.primary}
|
||||||
sx={{ wordBreak: "break-word" }}
|
sx={{ wordBreak: "break-word" }}
|
||||||
>
|
>
|
||||||
{currentQuestion.title}
|
{currentQuestion.title}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
marginTop: "20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
format="DD/MM/YYYY"
|
||||||
|
slots={{
|
||||||
|
openPickerIcon: () => (
|
||||||
|
<CalendarIcon
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
"& path": { stroke: theme.palette.primary.main },
|
||||||
flexDirection: "column",
|
"& rect": { stroke: theme.palette.primary.main },
|
||||||
width: "100%",
|
|
||||||
marginTop: "20px",
|
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<DatePicker
|
),
|
||||||
format="DD/MM/YYYY"
|
}}
|
||||||
slots={{
|
value={currentAnswer}
|
||||||
openPickerIcon: () => (
|
onChange={async (date) => {
|
||||||
<CalendarIcon
|
if (isSending || !date) return;
|
||||||
sx={{
|
|
||||||
"& path": { stroke: theme.palette.primary.main },
|
|
||||||
"& rect": { stroke: theme.palette.primary.main },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
value={currentAnswer}
|
|
||||||
onChange={async (date) => {
|
|
||||||
if (isSending || !date) return;
|
|
||||||
|
|
||||||
setIsSending(true);
|
setIsSending(true);
|
||||||
try {
|
try {
|
||||||
await sendAnswer({
|
await sendAnswer({
|
||||||
questionId: currentQuestion.id,
|
questionId: currentQuestion.id,
|
||||||
body: moment(date).format("YYYY.MM.DD"),
|
body: moment(date).format("YYYY.MM.DD"),
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
preview
|
preview,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAnswer(currentQuestion.id, date, 0);
|
updateAnswer(currentQuestion.id, date, 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
enqueueSnackbar("ответ не был засчитан");
|
enqueueSnackbar("ответ не был засчитан");
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsSending(false);
|
setIsSending(false);
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
openPickerButton: {
|
openPickerButton: {
|
||||||
sx: {
|
sx: {
|
||||||
p: 0,
|
p: 0,
|
||||||
},
|
},
|
||||||
"data-cy": "open-datepicker",
|
"data-cy": "open-datepicker",
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
sx: { backgroundColor: theme.palette.background.default },
|
sx: { backgroundColor: theme.palette.background.default },
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
"& .MuiInputBase-root": {
|
"& .MuiInputBase-root": {
|
||||||
backgroundColor: settings.cfg.design
|
backgroundColor: settings.cfg.design
|
||||||
? quizThemes[settings.cfg.theme].isLight
|
? quizThemes[settings.cfg.theme].isLight
|
||||||
? "#F2F3F7"
|
? "#F2F3F7"
|
||||||
: "rgba(154,154,175, 0.2)"
|
: "rgba(154,154,175, 0.2)"
|
||||||
: quizThemes[settings.cfg.theme].isLight
|
: quizThemes[settings.cfg.theme].isLight
|
||||||
? "white"
|
? "white"
|
||||||
: theme.palette.background.default,
|
: theme.palette.background.default,
|
||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
maxWidth: "250px",
|
maxWidth: "250px",
|
||||||
pr: "30px",
|
pr: "30px",
|
||||||
"& input": {
|
"& input": {
|
||||||
py: "11px",
|
py: "11px",
|
||||||
pl: "20px",
|
pl: "20px",
|
||||||
lineHeight: "19px",
|
lineHeight: "19px",
|
||||||
},
|
},
|
||||||
"& fieldset": {
|
"& fieldset": {
|
||||||
borderColor: "#9A9AAF",
|
borderColor: "#9A9AAF",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -109,6 +109,7 @@ export interface QuizConfig {
|
|||||||
};
|
};
|
||||||
meta: string;
|
meta: string;
|
||||||
yandexMetricNumber: number | undefined;
|
yandexMetricNumber: number | undefined;
|
||||||
|
vkMetricNumber: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormContactFieldName =
|
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) => {
|
export const useYandexMetrics = (yandexMetricNumber: number | undefined) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
|
yandexMetricNumber &&
|
||||||
typeof yandexMetricNumber === "number" &&
|
typeof yandexMetricNumber === "number" &&
|
||||||
!Number.isNaN(yandexMetricNumber)
|
!Number.isNaN(yandexMetricNumber)
|
||||||
) {
|
) {
|
||||||
@ -22,6 +23,7 @@ export const useYandexMetrics = (yandexMetricNumber: number | undefined) => {
|
|||||||
webvisor:true
|
webvisor:true
|
||||||
});
|
});
|
||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
|
|
||||||
const noscript = document.createElement("noscript");
|
const noscript = document.createElement("noscript");
|
||||||
|
Loading…
Reference in New Issue
Block a user