PageSourceSearch

https://pierceflooring.com/wp-content/plugins/roomvo-form-webhook-handler/form-webhook-handler.js?ver=2.3.1

js pierceflooring.com collected 2026-10-08 03:12:47 UTC 11,292 bytes, 373 lines download raw bytes

1// Helper function to retrieve a specific cookie by name
2function getCookie(name) {
3  const value = `; ${document.cookie}`;
4  const parts = value.split(`; ${name}=`);
5  if (parts.length === 2) return parts.pop().split(";").shift();
6}
7
8function parseJsonCookie(cookieVal) {
9  if (!cookieVal) return null;
10  try {
11    return JSON.parse(cookieVal);
12  } catch (e1) {
13    try {
14      return JSON.parse(decodeURIComponent(cookieVal));
15    } catch (e2) {
16      return null;
17    }
18  }
19}
20
21
22
23// Helper function to log a JavaScript error
24function logJSError(message) {
25  const errorData = {
26    message: message,
27    url: window.location.href,
28    timestamp: new Date().toISOString(),
29  };
30
31  fetch("/wp-json/form-webhook/v1/log-js-error", {
32    method: "POST",
33    headers: {
34      "Content-Type": "application/json",
35    },
36    body: JSON.stringify(errorData),
37  }).catch((err) => {
38    console.error("Failed to send error to server:", err);
39    console.error("Original error:", message);
40  });
41}
42
43function updateKadenceVisitorId(roomvoForm) {
44  if (!roomvoForm) return;
45
46
47  const visitorIdInput = roomvoForm.querySelector('input[data-label="visitor_id"]');
48  if (!visitorIdInput) return;
49  const rawCookie = getCookie("ffvisitorids");
50  const parsed = parseJsonCookie(rawCookie);
51  if (!parsed || typeof parsed !== "object") return;
52
53  let visitorId = null;
54
55  // 1) Prefer ffvendorurlpath if it matches a key in ffvisitorids
56  const vendorKeyFromCookie = getCookie("ffvendorurlpath");
57  if (vendorKeyFromCookie && Object.prototype.hasOwnProperty.call(parsed, vendorKeyFromCookie)) {
58    visitorId = parsed[vendorKeyFromCookie];
59  } else {
60    // 2) Existing behavior: use current field value as key
61    const visitorVendorID = visitorIdInput.value;
62    if (visitorVendorID && Object.prototype.hasOwnProperty.call(parsed, visitorVendorID)) {
63      visitorId = parsed[visitorVendorID];
64    } else {
65      // 3) Final fallback
66      const vals = Object.values(parsed);
67      visitorId = vals.length > 0 ? vals[0] : null;
68    }
69  }
70
71  if (!visitorId) return;
72
73  visitorIdInput.value = visitorId;
74  visitorIdInput.dispatchEvent(new Event("input", { bubbles: true }));
75  visitorIdInput.dispatchEvent(new Event("change", { bubbles: true }));
76}
77
78// Populates the Kadence form visitor_id field
79function processKadenceFormField(visitorIdInput, rawCookie) {
80  if (!visitorIdInput || !rawCookie) return;
81
82  const visitorVendorID = visitorIdInput.value;
83
84  try {
85    const parsed = parseJsonCookie(rawCookie);
86    let visitorId = null;
87
88    if (
89      visitorVendorID &&
90      parsed &&
91      typeof parsed === "object" &&
92      Object.prototype.hasOwnProperty.call(parsed, visitorVendorID)
93    ) {
94      visitorId = parsed[visitorVendorID];
95    } else if (
96      parsed &&
97      typeof parsed === "object" &&
98      Object.keys(parsed).length > 0
99    ) {
100      visitorId = Object.values(parsed)[0];
101    }
102
103    if (visitorId) {
104      visitorIdInput.value = visitorId;
105      visitorIdInput.dispatchEvent(new Event("input", { bubbles: true }));
106      visitorIdInput.dispatchEvent(new Event("change", { bubbles: true }));
107    }
108  } catch (e) {
109    const parseErrorMsg = "Error parsing ffvisitorids cookie: " + e.message;
110    console.error(parseErrorMsg);
111    logJSError(parseErrorMsg);
112  }
113}
114
115// Initialize Form Handlers - Called after the cookie pulling is complete
116function initializeFormHandlers(rawCookie, roomvoForm, ameliaForm) {
117  const locationURL = window.location.href;
118  // --- Logic for Kadence / Roomvo Forms ---
119  if (roomvoForm) {
120    const maxFieldRetries = 20; // 10 seconds
121    const fieldRetryInterval = 500;
122    let fieldRetryCount = 0;
123
124    function findKadenceField() {
125      const visitorIdInput = roomvoForm.querySelector(
126        'input[data-label="visitor_id"]'
127      );
128      if (visitorIdInput) {
129        updateKadenceVisitorId(roomvoForm);
130      } else if (fieldRetryCount < maxFieldRetries) {
131        fieldRetryCount++;
132        setTimeout(findKadenceField, fieldRetryInterval);
133      } else {
134        console.error(
135          "Please add a visitor_id field in this Kadence Roomvo form. Field not found after 10 seconds.",
136          roomvoForm
137        );
138      }
139    }
140
141    findKadenceField();
142  }
143
144  // --- Logic for Amelia Forms ---
145  if (ameliaForm) {
146    // Define Amelia custom field IDs
147    const visitorInputID = 3;
148    const locationUrlInputID = 4;
149    const utmSourceID = 5;
150    const utmMediumID = 6;
151    const utmCampaignID = 7;
152    const utmTermID = 8;
153
154    window.ameliaActions = {
155      InitInfoStep: function (success = null, error = null, data) {
156        const visitorIDInputWrapper = document.querySelector(
157          `#am-cf-${visitorInputID}`
158        );
159        const locationUrlWrapper = document.querySelector(
160          `#am-cf-${locationUrlInputID}`
161        );
162        const utmSourceIDInputWrapper = document.querySelector(
163          `#am-cf-${utmSourceID}`
164        );
165        const utmMediumIDInputWrapper = document.querySelector(
166          `#am-cf-${utmMediumID}`
167        );
168        const utmCampaignIDInputWrapper = document.querySelector(
169          `#am-cf-${utmCampaignID}`
170        );
171        const utmTermIDInputWrapper = document.querySelector(
172          `#am-cf-${utmTermID}`
173        );
174
175        const fieldsToHide = [
176          visitorIDInputWrapper,
177          locationUrlWrapper,
178          utmSourceIDInputWrapper,
179          utmMediumIDInputWrapper,
180          utmCampaignIDInputWrapper,
181          utmTermIDInputWrapper,
182        ];
183
184        fieldsToHide.forEach((field) => {
185          if (field) {
186            field.style.display = "none";
187          }
188        });
189
190        const locationUrlInput = document.querySelector(
191          `#am-cf-${locationUrlInputID} input`
192        );
193
194        if (locationUrlInput) {
195          locationUrlInput.value = locationURL;
196          locationUrlInput.dispatchEvent(
197            new Event("input", { bubbles: true })
198          );
199          locationUrlInput.dispatchEvent(
200            new Event("change", { bubbles: true })
201          );
202        }
203
204        (async () => {
205          try {
206            const response = await fetch("/wp-json/vendor-id/v1/get");
207            const data = await response.json();
208            const vendorId = data.vendor_id;
209
210            if (!vendorId) {
211              console.warn("Vendor ID not found in API response for Amelia.");
212              return;
213            }
214
215            const visitorIdInputAmelia = document.querySelector(
216              `#am-cf-${visitorInputID} input`
217            );
218
219            if (!visitorIdInputAmelia) {
220              console.warn(
221                `Amelia Visitor ID input field #am-cf-${visitorInputID} not found.`
222              );
223              return;
224            }
225
226            if (!rawCookie) {
227              console.warn("ffvisitorids cookie not found for Amelia.");
228              return;
229            }
230
231            let visitorId = null;
232
233            try {
234              const parsed = parseJsonCookie(rawCookie);
235
236              if (parsed && typeof parsed === "object") {
237                visitorId = parsed[vendorId] || Object.values(parsed)[0];
238              }
239            } catch (e) {
240              console.error("Error parsing ffvisitorids cookie for Amelia", e);
241              return;
242            }
243
244            if (visitorId) {
245              visitorIdInputAmelia.value = visitorId;
246              visitorIdInputAmelia.dispatchEvent(
247                new Event("input", { bubbles: true })
248              );
249              visitorIdInputAmelia.dispatchEvent(
250                new Event("change", { bubbles: true })
251              );
252            }
253          } catch (err) {
254            console.error(
255              "Unexpected error during Amelia visitor ID handling:",
256              err
257            );
258          }
259        })();
260
261        // Fill hidden UTM fields from URL parameters
262        const params = new URL(window.location.href).searchParams;
263
264        const utmSource = params.get("utm_source");
265        const utmMedium = params.get("utm_medium");
266        const utmCampaign = params.get("utm_campaign");
267        const utmTerm = params.get("utm_term");
268
269        const utmSourceInput = document.querySelector(
270          `#am-cf-${utmSourceID} input`
271        );
272        const utmMediumInput = document.querySelector(
273          `#am-cf-${utmMediumID} input`
274        );
275        const utmCampaignInput = document.querySelector(
276          `#am-cf-${utmCampaignID} input`
277        );
278        const utmTermInput = document.querySelector(
279          `#am-cf-${utmTermID} input`
280        );
281
282        function updateAmeliaField(inputElement, value, fieldName) {
283          if (inputElement && value) {
284            inputElement.value = value;
285            inputElement.dispatchEvent(new Event("input", { bubbles: true }));
286            inputElement.dispatchEvent(new Event("change", { bubbles: true }));
287          } else if (value && !inputElement) {
288            console.warn(
289              `Amelia ${fieldName} input field not found, but value exists.`
290            );
291          }
292        }
293
294        updateAmeliaField(utmSourceInput, utmSource, "utm_source");
295        updateAmeliaField(utmMediumInput, utmMedium, "utm_medium");
296        updateAmeliaField(utmCampaignInput, utmCampaign, "utm_campaign");
297        updateAmeliaField(utmTermInput, utmTerm, "utm_term");
298      },
299    };
300  }
301}
302
303// Get ffvisitorids cookie once, then initialize all matching forms individually
304function findCookieAndInitializeAll(roomvoForms, ameliaForms) {
305  const maxRetries = 20;
306  const retryInterval = 500;
307  let retryCount = 0;
308
309  const cookieIntervalID = setInterval(() => {
310    const cookie = getCookie("ffvisitorids");
311
312    if (cookie) {
313      clearInterval(cookieIntervalID);
314
315      roomvoForms.forEach(function (form) {
316        initializeFormHandlers(cookie, form, null);
317      });
318
319      ameliaForms.forEach(function (form) {
320        initializeFormHandlers(cookie, null, form);
321      });
322
323      return;
324    }
325
326    if (retryCount >= maxRetries) {
327      clearInterval(cookieIntervalID);
328
329      const errorMsg = "ffvisitorids cookie not found after 10 seconds.";
330      console.error(errorMsg + " URL: " + window.location.href);
331      logJSError(errorMsg);
332
333      roomvoForms.forEach(function (form) {
334        initializeFormHandlers(undefined, form, null);
335      });
336
337      ameliaForms.forEach(function (form) {
338        initializeFormHandlers(undefined, null, form);
339      });
340
341      return;
342    }
343
344    retryCount++;
345  }, retryInterval);
346}
347
348// Run the script after the DOM is fully loaded
349document.addEventListener("DOMContentLoaded", function () {
350  const roomvoForms = document.querySelectorAll(
351    "div.roomvo-contact-form>form.kb-advanced-form"
352  );
353
354  const ameliaForms = document.querySelectorAll(".amelia-form");
355
356  // If there are no supported forms on this page, stop.
357  // Normal forms without the Roomvo or Amelia class are ignored.
358  if (!roomvoForms.length && !ameliaForms.length) {
359    return;
360  }
361  // Listen once, then update every Roomvo form on the page.
362  if (roomvoForms.length) {
363    window.addEventListener("dlh-store-changed", function () {
364      setTimeout(function () {
365        roomvoForms.forEach(function (form) {
366          updateKadenceVisitorId(form);
367        });
368      }, 150);
369    });
370  }
371
372  findCookieAndInitializeAll(roomvoForms, ameliaForms);
373});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.