PluginProbe
Extendify / 2.2.0
Extendify v2.2.0
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / src / Launch / hooks / useTelemetry.js

useTelemetry.js in Extendify 2.2.0, at src/Launch/hooks/useTelemetry.js

192 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useEffect, useRef, useState } from '@wordpress/element';
2 import { INSIGHTS_HOST } from '@constants';
3 import { useGlobalStore } from '@launch/state/Global';
4 import { usePagesStore } from '@launch/state/Pages';
5 import { usePagesSelectionStore } from '@launch/state/pages-selections';
6 import { useUserSelectionStore } from '@launch/state/user-selections';
7
8 // Dev note: This entire section is opt-in only when partnerID is set as a constant
9 export const useTelemetry = () => {
10 const {
11 sitePlugins,
12 siteStructure,
13 variation,
14 siteProfile,
15 siteObjective,
16 siteQA,
17 attempt,
18 urlParameters,
19 } = useUserSelectionStore();
20 const { pages: selectedPages, style: selectedStyle } =
21 usePagesSelectionStore();
22 const { generating } = useGlobalStore();
23 const { pages, currentPageIndex, preselectedPages } = usePagesStore();
24 const [stepProgress, setStepProgress] = useState([]);
25 const [viewedStyles, setViewedStyles] = useState(new Set());
26 const running = useRef(false);
27 const firstRun = useRef(true);
28
29 useEffect(() => {
30 const p = [...pages].map((p) => p[0]);
31 // Add pages as they move around
32 setStepProgress((progress) => {
33 const withoutSkipped = progress.filter((p) => !preselectedPages.has(p));
34 // Return early if launched, or on the same page
35 if ([p[currentPageIndex], 'launched'].includes(progress?.at(-1))) {
36 return withoutSkipped;
37 }
38 return [...withoutSkipped, p[currentPageIndex]];
39 });
40 }, [currentPageIndex, pages, preselectedPages]);
41
42 useEffect(() => {
43 if (!generating) return;
44 // They pressed Launch
45 setStepProgress((progress) => [...progress, 'launched']);
46 }, [generating]);
47
48 useEffect(() => {
49 if (!Object.keys(selectedStyle ?? {})?.length) return;
50 // Add selectedStyle to the set
51 setViewedStyles((styles) => {
52 const newStyles = new Set(styles);
53 newStyles.add(selectedStyle);
54 return newStyles;
55 });
56 }, [selectedStyle]);
57
58 useEffect(() => {
59 let id = 0;
60 let innerId = 0;
61 const timeout = firstRun.current
62 ? // Send the first request immediately,
63 0
64 : // if on page 0, wait 2s
65 currentPageIndex === 0
66 ? 2000
67 : // Every other request will be 1s
68 1000;
69 firstRun.current = false;
70 id = window.setTimeout(() => {
71 if (running.current) return;
72 running.current = true;
73 const controller = new AbortController();
74 innerId = window.setTimeout(() => {
75 running.current = false;
76 controller.abort();
77 }, 900);
78
79 fetch(`${INSIGHTS_HOST}/api/v1/launch`, {
80 method: 'POST',
81 headers: {
82 'Content-type': 'application/json',
83 Accept: 'application/json',
84 'X-Extendify': 'true',
85 },
86 signal: controller.signal,
87 body: JSON.stringify({
88 siteType: siteProfile?.aiSiteType,
89 siteCategory: siteProfile?.aiSiteCategory,
90 siteCreatedAt: window.extSharedData?.siteCreatedAt,
91 style: variation?.title,
92 siteStructure,
93 siteObjective,
94 pages: selectedPages?.map((p) => p.slug),
95 sitePlugins: sitePlugins?.map((p) => p?.name),
96 lastCompletedStep: stepProgress?.at(-1),
97 progress: stepProgress,
98 preSelect: [...preselectedPages],
99 stylesViewed: [...viewedStyles]
100 .filter((s) => s?.variation)
101 .map((s) => s.variation.title),
102 insightsId: window.extSharedData?.siteId,
103 activeTests:
104 window.extOnbData?.activeTests?.length > 0
105 ? JSON.stringify(window.extOnbData?.activeTests)
106 : undefined,
107 hostPartner: window.extSharedData?.partnerId,
108 language: window.extSharedData?.wpLanguage,
109 siteURL: window.extSharedData?.homeUrl,
110 siteQuestions: siteQA?.questions.map((q) => ({
111 id: q?.id,
112 question: q?.question,
113 answerUser: q?.answerUser || null,
114 answerAI: q?.answerAI || null,
115 group: q?.group || null,
116 extraFields: q?.extraFields
117 ? q?.extraFields.map((ef) => ({
118 question: ef?.id,
119 answer: ef?.answer || null,
120 }))
121 : null,
122 })),
123 showHiddenQuestions: Boolean(siteQA?.showHidden),
124 attempt,
125 enabledFeatures: window.extSharedData?.showSiteQuestions
126 ? ['site-questions']
127 : [],
128 urlParameters: Object.fromEntries(
129 Object.entries(urlParameters)
130 .map(([key, value]) => {
131 if (key === 'tone' && Array.isArray(value)) {
132 return [key, value.map((t) => t.value)];
133 }
134 if (key === 'skip' && Array.isArray(value)) {
135 return [key, value];
136 }
137 return [key, value];
138 })
139 .filter(
140 ([_, value]) =>
141 value !== null &&
142 value !== '' &&
143 (!Array.isArray(value) || value.length > 0),
144 ),
145 ),
146 extra: {
147 userAgent: window?.navigator?.userAgent,
148 vendor: window?.navigator?.vendor || 'unknown',
149 platform:
150 window?.navigator?.userAgentData?.platform ||
151 window?.navigator?.platform ||
152 'unknown',
153 mobile: window?.navigator?.userAgentData?.mobile,
154 width: window.innerWidth,
155 height: window.innerHeight,
156 screenHeight: window.screen.height,
157 screenWidth: window.screen.width,
158 orientation: window.screen.orientation?.type,
159 touchSupport:
160 'ontouchstart' in window || navigator.maxTouchPoints > 0,
161 },
162 }),
163 })
164 .catch(() => undefined)
165 .finally(() => {
166 running.current = false;
167 });
168 }, timeout);
169 return () => {
170 running.current = false;
171 [id, innerId].forEach((i) => window.clearTimeout(i));
172 };
173 }, [
174 selectedPages,
175 selectedStyle,
176 pages,
177 stepProgress,
178 viewedStyles,
179 currentPageIndex,
180 sitePlugins,
181 siteProfile?.aiSiteType,
182 siteProfile?.aiSiteCategory,
183 siteStructure,
184 siteObjective,
185 variation,
186 preselectedPages,
187 siteQA,
188 attempt,
189 urlParameters,
190 ]);
191 };
192