/* Nordics Form Tracker - Form Start Event + Form Data Capture */ (function() { var formStarted = false; function onFocusIn() { if (!formStarted) { try { window.parent.postMessage('form_started', '*'); } catch (e) { // silently ignore postMessage errors } formStarted = true; console.log('[FormStart] form_started'); } } /** * Capture all form fields and their values dynamically * Skips fields with data-gtm-ignore attribute * @returns {object} Object containing all form field names and values */ function captureFormData() { var formData = {}; // Get all input fields var inputs = document.querySelectorAll('input'); inputs.forEach(function(input) { // Skip hidden input fields (used for metadata) if (input.type === 'hidden') { return; } // Skip fields with data-gtm-ignore attribute if (input.hasAttribute('data-gtm-ignore')) { return; } var name = input.name || input.id; if (name) { if (input.type === 'checkbox') { // Single checkbox (e.g. consent) should emit boolean; groups emit arrays. var checkboxGroup = document.querySelectorAll('input[type="checkbox"][name="' + name + '"]'); var isSingleCheckbox = checkboxGroup.length === 1; var hasMeaningfulValue = input.hasAttribute('value') && input.value !== 'on'; // If checkbox has default browser value ('on'), treat as boolean flag. if (isSingleCheckbox || !hasMeaningfulValue) { var booleanKey = input.id || name; formData[booleanKey] = input.checked; } else { if (input.checked) { if (Array.isArray(formData[name])) { formData[name].push(input.value); } else if (formData[name] !== undefined) { formData[name] = [formData[name], input.value]; } else { formData[name] = [input.value]; } } else if (formData[name] === undefined) { formData[name] = []; } } } else if (input.type === 'radio') { // Only add checked radio buttons if (formData[name] === undefined) { formData[name] = null; } if (input.checked) { formData[name] = input.value; } } else { formData[name] = input.value || null; } } }); // Get all select fields var selects = document.querySelectorAll('select'); selects.forEach(function(select) { // Skip fields with data-gtm-ignore attribute if (select.hasAttribute('data-gtm-ignore')) { return; } var name = select.name || select.id; if (name) { formData[name] = select.value || null; } }); // Get all textarea fields var textareas = document.querySelectorAll('textarea'); textareas.forEach(function(textarea) { // Skip fields with data-gtm-ignore attribute if (textarea.hasAttribute('data-gtm-ignore')) { return; } var name = textarea.name || textarea.id; if (name) { formData[name] = textarea.value || null; } }); return formData; } /** * Post a form_submitted event to parent with dynamically captured form data * @param {object} [payloadObject] Optional object to use instead of auto-captured form fields */ function postFormSubmitted(payloadObject) { var hasPayloadObject = payloadObject && typeof payloadObject === 'object' && !Array.isArray(payloadObject); var capturedData = hasPayloadObject ? payloadObject : captureFormData(); // Include Form Page Url for better context in GTM & Segment var submitMessage = { event: 'form_submitted', ...capturedData, formUrl: window.location.href }; try { window.parent.postMessage(submitMessage, '*'); // Log what was submitted console.log('[FormStart] form_submitted', submitMessage); } catch (e) { // silently ignore postMessage errors } } // Expose function globally so other scripts can call it from form level window.postFormSubmitted = postFormSubmitted; // Attach listener to the whole document document.addEventListener('focusin', onFocusIn, true); })();