PageSourceSearch

https://hrone.cloud/wp-content/themes/hrone-child/assets/js/ppc-form-submit.js?ver=982007369

js hrone.cloud collected 2026-10-01 13:10:20 UTC 13,448 bytes, 301 lines download raw bytes

1/**
2 * PPC Form Submission Handler
3 * Submits PPC form directly to HubSpot API (no AJAX/backend required)
4 */
5
6(function ($) {
7    'use strict';
8
9    /**
10     * Lightweight client-side sanitizers to avoid pushing unsafe/unexpected values
11     * into 3rd-party APIs. Server-side sanitization should still be enforced.
12     */
13    function sanitizePlainText(value, maxLen = 250) {
14        if (value === null || value === undefined) return '';
15        let str = String(value);
16        // Strip HTML tags
17        str = str.replace(/<[^>]*>/g, '');
18        // Remove ASCII control chars
19        str = str.replace(/[\u0000-\u001F\u007F]/g, '');
20        // Collapse whitespace
21        str = str.replace(/\s+/g, ' ').trim();
22        if (maxLen && str.length > maxLen) str = str.slice(0, maxLen);
23        return str;
24    }
25
26    function sanitizeEmail(value) {
27        const email = sanitizePlainText(value, 320).toLowerCase();
28        return email.replace(/\s+/g, '');
29    }
30
31    function sanitizePhoneIN(value) {
32        const digits = String(value ?? '').replace(/\D/g, '');
33        return digits.length <= 10 ? digits : digits.slice(-10);
34    }
35
36    function sanitizeUrl(value) {
37        const raw = sanitizePlainText(value, 2000);
38        if (!raw) return '';
39        try {
40            const u = new URL(raw, window.location.origin);
41            if (u.protocol !== 'http:' && u.protocol !== 'https:') return '';
42            return u.href;
43        } catch (e) {
44            return '';
45        }
46    }
47
48    function sanitizePpcFormData(formData) {
49        const safe = { ...(formData || {}) };
50
51        safe.ppc_email = sanitizeEmail(safe.ppc_email);
52        safe.phone_ppc = sanitizePhoneIN(safe.phone_ppc);
53        safe.city = sanitizePlainText(safe.city, 120);
54        safe.state_code = sanitizePlainText(safe.state_code, 50);
55        safe.number_of_employee_v1 = sanitizePlainText(safe.number_of_employee_v1, 50);
56
57        safe.utm_source = sanitizePlainText(safe.utm_source, 120);
58        safe.utm_medium = sanitizePlainText(safe.utm_medium, 120);
59        safe.utm_campaign = sanitizePlainText(safe.utm_campaign, 120);
60        safe.utm_content = sanitizePlainText(safe.utm_content, 120);
61        safe.utm_term = sanitizePlainText(safe.utm_term, 120);
62
63        safe.permalink = sanitizeUrl(safe.permalink);
64        safe.page_title = sanitizePlainText(safe.page_title, 200);
65
66        return safe;
67    }
68
69    // HubSpot API Configuration
70    const HUBSPOT_PORTAL_ID = '7277696';
71    const HUBSPOT_FORM_GUID = '0a36628e-332f-49ac-925e-3c568d8c4353';
72    const HUBSPOT_API_URL = 'https://api.hsforms.com/submissions/v3/integration/submit/' + HUBSPOT_PORTAL_ID + '/' + HUBSPOT_FORM_GUID;
73
74    $(document).ready(function () {
75        // PPC Form Submit Handler - handle both form submit and button click
76        $("#ppcform").on('submit', function (event) {
77            event.preventDefault();
78            // Trigger the click handler logic
79            $("#submitppc").trigger('click');
80        });
81
82        $("#submitppc").click(function (event) {
83            event.preventDefault();
84
85            var state = $('#input-box-city').attr('data-state');
86            var isValid = true;
87            var email = $('#ppc_email').val();
88            var phoneNum = $('#phone_ppc').val();
89
90            // Check if base domains are loaded (for email validation)
91            if (typeof baseDomainsLoaded !== 'undefined' && !baseDomainsLoaded) {
92                $('.email_error').html('Please wait while the email domains are being loaded. Try again.');
93                isValid = false;
94            }
95
96            // Validate required text/email fields (but skip hidden fields)
97            $(this).closest('form').find("input[type='text']:not(.hidden), input[type='email']").each(function () {
98                if ($(this).val().trim() === '' && $(this).attr('required')) {
99                    isValid = false;
100                    $(this).addClass('error');
101                } else {
102                    $(this).removeClass('error');
103                }
104            });
105
106            // Validate phone
107            var phoneRegex = /^[6-9]\d{9}$/;
108            if (!phoneRegex.test(phoneNum)) {
109                $('#phone_ppc').addClass('error');
110                // Handle both phone_error and phone_error_PPC selectors
111                $('.phone_error, .phone_error_PPC').html('Insert a valid number ');
112                isValid = false;
113            } else {
114                $('#phone_ppc').removeClass('error');
115                $('.phone_error, .phone_error_PPC').html('');
116            }
117
118            // Validate email
119            if (email.length > 0) {
120                var email = $('#ppc_email').val().trim().toLowerCase();
121                if (typeof validateEmail !== 'undefined' && !validateEmail(email)) {
122                    $('#ppc_email').addClass('error');
123                    $('.email_error').html('Please insert valid work email. ');
124                    isValid = false;
125                } else {
126                    $('#ppc_email').removeClass('error');
127                    $('.email_error').html('');
128                }
129            }
130
131            // Validate city using global autocomplete data
132            function validateCity() {
133                if (typeof inputBox !== 'undefined' && typeof availableKeywords !== 'undefined') {
134                    const inputCity = inputBox.value.trim();
135                    const cityExists = availableKeywords.some(({ city }) => city === inputCity);
136                    if (!cityExists) {
137                        $(inputBox).addClass('error');
138                        $('.city-error').html('City not found in the list. Please select a valid city.');
139                        return false;
140                    } else {
141                        $('.city-error').html('');
142                    }
143                }
144                return true;
145            }
146
147            if (!validateCity()) {
148                isValid = false;
149            }
150
151            // Validate employee count
152            var formId = $(this).closest("form").attr("id");
153            var form = document.getElementById(formId);
154            var no_of_employee_exists = form && form.querySelector('#no_of_employee') !== null;
155            if (no_of_employee_exists) {
156                var no_of_employee_field = $('#no_of_employee');
157                if (no_of_employee_field.length > 0) {
158                    var no_of_employee = no_of_employee_field.val();
159                    // Also check the value attribute for floating form selects (they set value attribute on click)
160                    var selectValue = no_of_employee || no_of_employee_field.attr('value') || '';
161                    if (!selectValue || selectValue === '') {
162                        isValid = false;
163                        no_of_employee_field.addClass('error');
164                        $('.employee_error').html('Please select the number of employees.');
165                    } else {
166                        no_of_employee_field.removeClass('error');
167                        $('.employee_error').html('');
168                    }
169                }
170            }
171
172            if (!isValid) {
173                return false;
174            }
175
176            // Capture form data for this specific form
177            const formData = captureFormData('ppcform');
178            formData.state_code = state;
179            const sanitizedFormData = sanitizePpcFormData(formData);
180
181            // Debug: Log form data to verify all fields are captured
182           // console.log('PPC Form Data (sanitized):', sanitizedFormData);
183
184            const hasAnyValue = Object.values(sanitizedFormData).some(value => value !== '');
185
186            if (!hasAnyValue) {
187                console.log('No form data found');
188                return false;
189            }
190
191            document.getElementById("submitppc").disabled = true;
192            var loaderEl = document.getElementById("loaderpopup3");
193            if (loaderEl) {
194                loaderEl.style.display = "block";
195            }
196
197            // Get HubSpot tracking cookie (hubspotutk) for API context
198            function getCookie(name) {
199                const value = `; ${document.cookie}`;
200                const parts = value.split(`; ${name}=`);
201                if (parts.length === 2) return parts.pop().split(';').shift();
202                return '';
203            }
204
205            const hubspotCookie = getCookie('hubspotutk') || '';
206
207            // PPC form doesn't have a name field, so we'll use email prefix as firstname or leave empty
208            // Extract first part of email as firstname if needed
209            const emailValue = sanitizedFormData.ppc_email || '';
210            let firstname = '';
211            let lastname = '';
212            if (emailValue) {
213                const emailPrefix = emailValue.split('@')[0];
214                // Use email prefix as firstname (optional - can be left empty)
215                firstname = emailPrefix || '';
216            }
217
218            // Prepare data for HubSpot API
219            const hubspotData = {
220                "submittedAt": new Date().toISOString(),
221                "fields": [
222                    { "objectTypeId": "0-1", "name": "firstname", "value": firstname },
223                    { "objectTypeId": "0-1", "name": "lastname", "value": lastname },
224                    { "objectTypeId": "0-1", "name": "email", "value": sanitizedFormData.ppc_email || '' },
225                    { "objectTypeId": "0-1", "name": "phone", "value": "+91" + (sanitizedFormData.phone_ppc || '') },
226                    { "objectTypeId": "0-1", "name": "city", "value": sanitizedFormData.city || '' },
227                    { "objectTypeId": "0-1", "name": "state_sap__cloned_", "value": state || '' },
228                    { "objectTypeId": "0-1", "name": "country", "value": "India" },
229                    { "objectTypeId": "0-1", "name": "number_of_employee_v1", "value": sanitizedFormData.number_of_employee_v1 || '' },
230                    { "objectTypeId": "0-1", "name": "utm_source", "value": sanitizedFormData.utm_source || '' },
231                    { "objectTypeId": "0-1", "name": "utm_medium", "value": sanitizedFormData.utm_medium || '' },
232                    { "objectTypeId": "0-1", "name": "utm_campaign", "value": sanitizedFormData.utm_campaign || '' },
233                    { "objectTypeId": "0-1", "name": "utm_content", "value": sanitizedFormData.utm_content || '' },
234                    { "objectTypeId": "0-1", "name": "utm_term", "value": sanitizedFormData.utm_term || '' }
235                ],
236                "context": {
237                    "hutk": hubspotCookie,
238                    "pageUri": sanitizedFormData.permalink || window.location.href,
239                    "pageName": sanitizedFormData.page_title || document.title
240                },
241                "legalConsentOptions": {
242                    "consent": {
243                        "consentToProcess": true,
244                        "text": "I agree to allow HROne to store and process my personal data."
245                    }
246                }
247            };
248
249            // Submit directly to HubSpot API (no AJAX/backend)
250            fetch(HUBSPOT_API_URL, {
251                method: 'POST',
252                headers: {
253                    'Content-Type': 'application/json'
254                },
255                body: JSON.stringify(hubspotData)
256            })
257                .then(response => response.json())
258                .then(data => {
259                    // Reset form and hide loader
260                    if ($('#ppcform').length) {
261                        $('#ppcform')[0].reset();
262                    }
263                    document.getElementById("submitppc").disabled = false;
264                    if (loaderEl) {
265                        loaderEl.style.display = "none";
266                    }
267
268                    // Optional success message (can be styled as needed)
269                    if (data.inlineMessage) {
270                        // You can add success message display here if needed
271                        // Similar to product form if there's a container for it
272                    }
273
274                    // Redirect to thank you page
275                    setTimeout(function () {
276                        const thankYouUrl = (typeof hronePpcForm !== 'undefined' && hronePpcForm.thankYouUrl)
277                            ? hronePpcForm.thankYouUrl
278                            : window.location.origin + '/thankyou';
279                        window.location.href = thankYouUrl;
280                    }, 1000);
281                })
282                .catch(error => {
283                    console.error('Error submitting PPC form:', error);
284                    document.getElementById("submitppc").disabled = false;
285                    if (loaderEl) {
286                        loaderEl.style.display = "none";
287                    }
288                    // Display error message
289                    const errorMsg = '<div class="hm-banner-msg"><div class="error-msg"><h2>Error!</h2>There was an error submitting your form. Please try again.</div></div>';
290                    // Try to find a container to show error, otherwise use alert
291                    if ($('.ppc-from').length) {
292                        $('.ppc-from').prepend(errorMsg);
293                    } else {
294                        alert('There was an error submitting your form. Please try again.');
295                    }
296                });
297        });
298    });
299
300})(jQuery);
301

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.