1/** 2 * GTM Analytics tracking utility 3 * Implements ICICI HFC GA4 Phase 1 GTM Tag Guidelines 4 */ 5 6// Prevent multiple initializations 7let isInitialized = false; 8// Initialize dataLayer if it doesn't exist 9 10import { getMetadata } from "./aem.js"; 11 12const pageName = getPageName().toLowerCase(); 13const loginInfo = getLoginInfo(); 14 15function hashCustomerID(id) { 16 if (!id) return null; 17 return btoa(new TextEncoder().encode(id).reduce((acc, byte) => acc + String.fromCharCode(byte), '')); 18} 19 20function getPageName() { 21 const pathname = window.location.pathname; 22 const segments = pathname.split('/').filter(segment => segment && segment !== 'en'); 23 return segments.length === 0 ? 'home' : segments.join(':'); 24} 25 26// function getJourneyName() { 27// const pathname = window.location.pathname; 28// const segments = pathname.split('/').filter(segment => segment && segment !== 'en'); 29// return segments.length === 0 ? 'home' : segments[0]; 30// } 31 32function getJourneyName() { 33 const keywords = getMetadata("keywords")?.toLowerCase() || ""; 34 35 const keywordMap = [ 36 { keyword: "lsp-dashboard", name: "loan-service" }, 37 { keyword: "lsp-header", name: "loan-service" }, 38 { keyword: "fd-customer-dashboard", name: "fixed deposit" }, 39 { keyword: "fd-broker-registration", name: "fixed deposit" }, 40 { keyword: "fd-security", name: "fixed deposit" }, 41 { keyword: "fd-login", name: "fixed deposit" }, 42 { keyword: "fd-dashboard", name: "fixed deposit" }, 43 { keyword: "app-track-dash", name: "view my application" }, 44 { keyword: "app-track-login", name: "view my application" }, 45 { keyword: "vma-dashboard", name: "view my application" }, 46 { keyword: "vma-login", name: "view my application" }, 47 { keyword: "dma-rp-header", name: "dma-rp" }, 48 { keyword: "dma-dashboard", name: "dma" }, 49 { keyword: "rp-dashboard", name: "rp" }, 50 { keyword: "payments-dashboard", name: "payments" }, 51 { keyword: "payments-header", name: "payments" }, 52 { keyword: "employee-assisted", name: "employee-assisted" }, 53 { keyword: "broker-assisted", name: "broker-assisted" }, 54 ]; 55 56 for (const { keyword, name } of keywordMap) { 57 if (keywords.includes(keyword)) return name; 58 } 59 60 // Fallback to first URL path segment 61 const segments = window.location.pathname 62 .split("/") 63 .filter((s) => s && s !== "en"); 64 65 return segments[0] ?? "home"; 66} 67 68function getPageChannel() { 69 const journeyName = getJourneyName(); 70 return `web:${journeyName}`; 71} 72 73function getLoginInfo() { 74 const token = sessionStorage.getItem('kyc-token') || localStorage.getItem('user-token') || sessionStorage.getItem("accessToken") || sessionStorage.getItem('vmlToken') || (sessionStorage.getItem("lspSession") ? JSON.parse(sessionStorage.getItem("lspSession")).secureToken : null); 75 const customerId = sessionStorage.getItem('customer-id') || localStorage.getItem('customer-id') || sessionStorage.getItem("loginCustId") || (sessionStorage.getItem("lspSession") ? JSON.parse(sessionStorage.getItem("lspSession")).mobileNo : null) || sessionStorage.getItem("LoggingCusID"); 76 77 return { 78 login_status: token ? 'logged-in' : 'guest', 79 customerID: hashCustomerID(token && customerId ? customerId : null) 80 }; 81} 82 83function trackPageView() { 84 85 const eventData = { 86 event: 'page_view', 87 page_name: pageName, 88 page_channel: getPageChannel().toLowerCase(), 89 login_status: loginInfo.login_status, 90 customerID: loginInfo.customerID 91 }; 92 93 if (pageName !== 'home') { 94 eventData.journey_name = getJourneyName().toLowerCase(); 95 } 96 97 console.log('ð¡ GTM page_view:', eventData); 98 window.dataLayer.push(eventData); 99} 100 101function trackClick(ctaName) { 102 103 const eventData = { 104 event: 'click', 105 cta_name: ctaName.toLowerCase(), 106 page_name: pageName, 107 login_status: loginInfo.login_status, 108 customerID: loginInfo.customerID 109 }; 110 111 if (pageName !== 'home') { 112 eventData.journey_name = getJourneyName().toLowerCase(); 113 } 114 115 console.log('ð±ï¸ GTM click:', eventData); 116 window.dataLayer.push(eventData); 117} 118 119function trackBannerClick(bannerName, ctaName, bannerPosition = null) { 120 121 const eventData = { 122 event: 'banner_click', 123 event_name: 'banner_click', 124 link_pagename: pageName, 125 banner_name: bannerName ? bannerName.toLowerCase() : null, 126 cta_name: ctaName ? ctaName.toLowerCase() : null, 127 login_status: loginInfo.login_status, 128 journey_name: getJourneyName().toLowerCase(), 129 customerID: loginInfo.customerID 130 }; 131 132 if (bannerPosition !== null) { 133 eventData.banner_position = String(bannerPosition); 134 } 135 136 console.log('ð¯ GTM banner_click:', eventData); 137 window.dataLayer.push(eventData); 138} 139 140function trackScroll(scrollPercent) { 141 142 const eventData = { 143 event: 'scroll', 144 page_name: pageName, 145 page_channel: getPageChannel().toLowerCase(), 146 login_status: loginInfo.login_status, 147 scrollPercent: scrollPercent, 148 customerID: loginInfo.customerID 149 }; 150 151 console.log('ð GTM scroll:', eventData); 152 window.dataLayer.push(eventData); 153} 154 155function trackSearch(searchTerm, customerID) { 156 157 const eventData = { 158 event: 'search', 159 cta_name: 'search initiated', 160 page_name: pageName, 161 journey_name: getJourneyName().toLowerCase(), 162 searchTerm: searchTerm.toLowerCase(), 163 login_status: loginInfo.login_status, 164 customerID: loginInfo.customerID || hashCustomerID(customerID) 165 }; 166 167 console.log('ð GTM search:', eventData); 168 window.dataLayer.push(eventData); 169} 170 171function trackSearchResults(searchTerm) { 172 173 const eventData = { 174 event: 'view_search_results', 175 page_name: pageName, 176 page_channel: getPageChannel().toLowerCase(), 177 login_status: loginInfo.login_status, 178 searchTerm: searchTerm.toLowerCase(), 179 journey_name: getJourneyName().toLowerCase(), 180 customerID: loginInfo.customerID 181 }; 182 183 console.log('ð GTM search results:', eventData); 184 window.dataLayer.push(eventData); 185} 186 187function trackFileDownload(fileName) { 188 189 190 const eventData = { 191 event: 'file_download', 192 cta_name: 'file download', 193 page_name: pageName, 194 fileName: fileName.toLowerCase(), 195 login_status: loginInfo.login_status, 196 customerID: loginInfo.customerID 197 }; 198 199 console.log('ð GTM file download:', eventData); 200 window.dataLayer.push(eventData); 201} 202 203function trackLoanAmountChange(loanAmount, bannerName = 'home loan mini calculator') { 204 205 const eventData = { 206 event: 'loan_amount_change', 207 cta_name: 'loan amount cursor', 208 page_name: pageName, 209 banner_name: bannerName, 210 loan_amount: loanAmount, 211 login_status: loginInfo.login_status, 212 customerID: loginInfo.customerID 213 }; 214 215 console.log('ð° GTM loan amount change:', eventData); 216 window.dataLayer.push(eventData); 217} 218 219function trackFDTenureChange(fdTenure, bannerName = 'fd mini calculator') { 220 221 const eventData = { 222 event: 'fd_tenure_change', 223 cta_name: 'fd tenure', 224 page_name: pageName, 225 banner_name: bannerName, 226 fd_tenure: fdTenure, 227 login_status: loginInfo.login_status, 228 customerID: loginInfo.customerID 229 }; 230 231 console.log('ð GTM FD tenure change:', eventData); 232 window.dataLayer.push(eventData); 233} 234 235// Form tracking analytics â Apply Now modal lead forms only 236// (home-loan, lead, lap-lead, bt, pmay, fd, property-auction, fill-details, careers, etc.) 237const FORM_FIELD_SELECTOR = 'input:not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]), select, textarea'; 238const trackedFormStarts = new WeakSet(); 239 240const FORM_ANALYTICS_IDS = { 241 'home-loan-form': 'hfc-hlf', 242 'lead-form': 'hfc-lf', 243 'lap-lead-form': 'hfc-laplf', 244 'bt-form': 'hfc-btf', 245 'pmay-form': 'hfc-pmayf', 246 'fd-cal-form': 'hfc-fdcf', 247 'property-auction-form': 'hfc-paf', 248 'careers-form': 'hfc-cf', 249 'fill-details': 'hfc-fdf', 250}; 251 252function isLeadForm(form) { 253 if (!(form instanceof HTMLFormElement)) return false;
254 const action = form.dataset.action || form.getAttribute('action') || ''; 255 if (!action.includes('/spreadsheet-apis/')) return false; 256 return Boolean(form.closest('.form-modal') || form.id === 'enquiry-form'); 257} 258 259function shouldTrackForm(form) { 260 if (!isLeadForm(form)) return false; 261 if (form.dataset.trackForms === 'false') return false; 262 return true; 263} 264 265function getFormActionSlug(form) { 266 const action = form.dataset.action || form.getAttribute('action') || ''; 267 if (!action) return ''; 268 try { 269 const pathname = action.startsWith('http') ? new URL(action).pathname : action; 270 return pathname.split('/').filter(Boolean).pop()?.replace(/\.json$/, '') || ''; 271 } catch { 272 return action.split('/').filter(Boolean).pop()?.replace(/\.json$/, '') || ''; 273 } 274} 275 276function getFormMetadata(form) { 277 const actionSlug = getFormActionSlug(form); 278 const formId = form.dataset.formId || FORM_ANALYTICS_IDS[actionSlug] || form.id || null; 279 const formName = form.dataset.formName || form.getAttribute('name') || actionSlug || form.className.split(/\s+/).filter(Boolean)[0] || 'unknown'; 280 281 return { 282 form_id: formId ? String(formId).toLowerCase() : null, 283 form_name: String(formName).toLowerCase(), 284 }; 285} 286 287function buildFormEventData(event, eventName, form) { 288 const { form_id, form_name } = getFormMetadata(form); 289 290 return { 291 event, 292 event_name: eventName, 293 link_pagename: pageName, 294 login_status: loginInfo.login_status, 295 journey_name: getJourneyName().toLowerCase(), 296 customerID: loginInfo.customerID, 297 form_id, 298 form_name, 299 }; 300} 301 302function trackFormStart(form) { 303 if (!shouldTrackForm(form) || trackedFormStarts.has(form)) return; 304 trackedFormStarts.add(form); 305 306 const eventData = buildFormEventData('form_start', 'form start', form); 307 console.log('ð GTM form_start:', eventData); 308 window.dataLayer.push(eventData); 309} 310 311function trackFormSubmit(form) { 312 if (!shouldTrackForm(form)) return; 313 314 const eventData = buildFormEventData('form_submit', 'form submit', form); 315 console.log('â GTM form_submit:', eventData); 316 window.dataLayer.push(eventData); 317} 318 319function initFormTracking() { 320 document.addEventListener('focusin', (event) => { 321 const field = event.target; 322 if (!field.matches?.(FORM_FIELD_SELECTOR)) return; 323 324 const form = field.closest('form'); 325 if (!form) return; 326 327 trackFormStart(form); 328 }, true); 329 330 document.addEventListener('change', (event) => { 331 const field = event.target; 332 if (!field.matches?.(FORM_FIELD_SELECTOR)) return; 333 334 const form = field.closest('form'); 335 if (!form) return; 336 337 trackFormStart(form); 338 }, true); 339} 340 341export function initGtagTracking() { 342 if (isInitialized) return; 343 isInitialized = true; 344 345 // Track page view immediately 346 trackPageView(); 347 348 // Check for search results to track 349 try { 350 const searchTerm = sessionStorage.getItem('search_term'); 351 if (searchTerm) { 352 trackSearchResults(searchTerm); 353 sessionStorage.removeItem('search_term'); 354 } 355 } catch (error) { 356 console.error('Error tracking search results page:', error); 357 } 358 359 // Track scroll events (25%, 50%, 75%, 100%) â throttled via rAF to reduce main-thread work 360 let scrollTracked = { 25: false, 50: false, 75: false, 100: false }; 361 let scrollTicking = false; 362 const onScroll = () => { 363 if (scrollTicking) return; 364 scrollTicking = true; 365 requestAnimationFrame(() => { 366 const scrollPercent = Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100); 367 [25, 50, 75, 100].forEach(threshold => { 368 if (scrollPercent >= threshold && !scrollTracked[threshold]) { 369 scrollTracked[threshold] = true; 370 trackScroll(`${threshold}%`); 371 } 372 }); 373 // Remove listener once all thresholds are hit 374 if (scrollTracked[25] && scrollTracked[50] && scrollTracked[75] && scrollTracked[100]) { 375 window.removeEventListener('scroll', onScroll); 376 } 377 scrollTicking = false; 378 }); 379 }; 380 window.addEventListener('scroll', onScroll, { passive: true }); 381 382 // Track clicks 383 document.addEventListener('click', (event) => { 384 const element = event.target.closest('a, button, [role="button"]'); 385 if (element) { 386 const ctaName = element.textContent?.trim() || 387 element.getAttribute('aria-label') || 388 element.getAttribute('title') || 389 'unknown'; 390 391 trackClick(ctaName); 392 393 // Check if it's a PDF download 394 const href = element.href || element.getAttribute('href') || ''; 395 if (href.toLowerCase().includes('.pdf')) { 396 const fileName = href.split('/').pop() || ctaName; 397 trackFileDownload(fileName); 398 } 399 } 400 }); 401 402 // Intercept fetch for error responses â only process API errors, skip successful c
402alls 403 const originalFetch = window.fetch; 404 window.fetch = async (...args) => { 405 const response = await originalFetch(...args); 406 const url = (typeof args[0] === 'string' ? args[0] : args[0]?.url) || ''; 407 const isApiCall = url.includes('icicihfc-micro-service'); 408 409 // Only clone and parse JSON for API error responses to avoid unnecessary work 410 if (isApiCall && response.status >= 400) { 411 try { 412 const data = await response.clone().json(); 413 const bodyStatusCode = data?.statusCode || data?.status; 414 trackError( 415 data?.message || data?.error || `http error ${response.status}`, 416 data?.errorCode || data?.code || `error${bodyStatusCode || response.status}`, 417 sessionStorage.getItem('customer-id') || localStorage.getItem('customer-id'), 418 getJourneyName() 419 ); 420 } catch { 421 trackError(`http error ${response.status}`, `error${response.status}`, null, getJourneyName()); 422 } 423 } 424 return response; 425 }; 426 427 initFormTracking(); 428} 429 430// FD journey analytics 431function trackFDJourneyEvent(eventType, customerID, customerType = 'existing customer', paymentDetails = {}){ 432 433 let event, eventName; 434 435 if (eventType === 'book_new_fd') { 436 event = 'book_new_fd'; 437 eventName = 'book new fd'; 438 } else if (eventType === 'payment_initiated') { 439 event = 'fd_payment_initiated'; 440 eventName = 'pay now'; 441 } else if (eventType === 'success') { 442 event = 'applyfd_success'; 443 eventName = 'applyfd-success'; 444 } else if (eventType === 'failure') { 445 event = 'applyfd_failure'; 446 eventName = 'applyfd-failure'; 447 } 448 449 const eventData = { 450 event: event, 451 event_name: eventName, 452 login_status: loginInfo.login_status, 453 journey_name: 'fixed deposit', 454 customer_type: customerType.toLowerCase(), 455 page_name: pageName, 456 customerID: loginInfo.customerID || hashCustomerID(customerID) 457 }; 458 459 // â NEW: Add payment details only for success/failure events 460 if (eventType === 'success' || eventType === 'failure') { 461 if (paymentDetails.transactionID) eventData.transactionID = paymentDetails.transactionID; 462 if (paymentDetails.fd_amount) eventData.amount = paymentDetails.fd_amount; 463 if (paymentDetails.payment_mode) eventData.payment_mode = paymentDetails.payment_mode; 464 if (paymentDetails.payment_method) eventData.payment_method = paymentDetails.payment_method; 465 } 466 467 // Add link_pagename only for book_new_fd and payment_initiated 468 // if (eventType === 'book_new_fd' || eventType === 'payment_initiated') { 469 // eventData.page_name = pageName; 470 // } 471 472 console.log(`ð GTM FD Journey (${event}):`, eventData); 473 window.dataLayer.push(eventData); 474} 475 476function trackApplyFDStep(stepNumber, stepName, customerID, customerType = 'existing customer') { 477 478 const eventData = { 479 event: `applyfd_step${stepNumber}`, 480 event_name: `applyfd-step${stepNumber}`, 481 step_name: stepName.toLowerCase(), 482 page_name: pageName, 483 login_status: loginInfo.login_status, 484 journey_name: 'fixed deposit', 485 customer_type: customerType.toLowerCase(), 486 customerID: loginInfo.customerID || hashCustomerID(customerID) 487 }; 488 489 console.log(`ð GTM apply FD step ${stepNumber}:`, eventData); 490 window.dataLayer.push(eventData); 491} 492 493function trackKYCVerifyStep(stepNumber, customerID, customerType = 'new customer') { 494 495 const eventData = { 496 event: stepNumber === 1 ? 'kycverify_start' : 'kycverify_success', 497 event_name: stepNumber === 1 ? 'kyc verify start' : 'kyc verify success', 498 step_name: `kycverify-step${stepNumber}`, 499 login_status: 'logged-in', 500 journey_name: 'fixed deposit', 501 customer_type: customerType.toLowerCase(), 502 customerID: loginInfo.customerID || hashCustomerID(customerID) 503 }; 504 505 console.log(`ð GTM KYC verify step ${stepNumber}:`, eventData); 506 window.dataLayer.push(eventData); 507} 508 509// VMA journey analytics 510function trackVMAEvent(event, eventName, customerID) { 511 512 const eventData = { 513 event: event, 514 event_name: eventName, 515 page_name: pageName, 516 login_status: loginInfo.login_status, 517 journey_name: 'view my application', 518 customerID: loginInfo.customerID || hashCustomerID(customerID) 519 }; 520 521 console.log(`ð GTM VMA Event (${event}):`, eventData); 522 window.dataLayer.push(eventData); 523} 524 525function trackVMAFieldEntry(fieldEvent) { 526 const eventData = { 527 event: fieldEvent, 528 event_name: fieldEvent, 529 link_pagename: pageName, 530 login_status: loginInfo.login_status, 531 journey_name: 'view my application', 532 customerID: loginInfo.customerID 533 }; 534 console.log(`ð GTM VMA Field (${fieldEvent}):`, JSON.stringify(eventData, null, 2)); 535 window.dataLayer.push(eventData); 536} 537 538// Login Fees interaction tracking 539function trackLoginFees(customerID) { 540 const eventData = { 541 event: 'login_fees', 542 event_name: 'login_fees', 543 link_pagename: pageName, 544 login_status: loginInfo.login_status, 545 journey_name: getJourneyName().toLowerCase(), 546 customerID: loginInfo.customerID || hashCustomerID(customerID) 547 }; 548 549 console.log('ð³ GTM login fees:', JSON.stringify(eventData, null, 2)); 550 window.dataLayer.push(eventData); 551} 552 553// Processing Fees interaction tracking 554function trackProcessingFees(customerID) { 555 const eventData = { 556 event: 'processing_fees', 557 event_name: 'processing_fees', 558 link_pagename: pageName, 559 login_status: loginInfo.login_status, 560 journey_name: getJourneyName().toLowerCase(), 561 customerID: loginInfo.customerID || hashCustomerID(customerID) 562 }; 563 564 console.log('ð³ GTM processing fees:', JSON.stringify(eventData, null, 2)); 565 window.dataLayer.push(eventData); 566} 567 568// VMA Login Fees Payment Success/Failure tracking 569function trackVMALoginFeesPayment(eventType, customerID, paymentDetails = {}) { 570 const isSuccess = eventType === 'success'; 571 572 const eventData = { 573 event: isSuccess ? 'vma_loginfees_success' : 'vma_loginfees_failure', 574 event_name: isSuccess ? 'vma_loginfees_success' : 'vma_loginfees_failure', 575 step_name: isSuccess ? 'success' : 'failure', 576 login_status: loginInfo.login_status, 577 journey_name: getJourneyName().toLowerCase(), 578 customerID: loginInfo.customerID || hashCustomerID(customerID) 579 }; 580 581 if (paymentDetails.transactionID) eventData.transactionID = paymentDetails.transactionID; 582 if (paymentDetails.amount) eventData.amount = paymentDetails.amount; 583 if (paymentDetails.payment_mode) eventData.payment_mode = paymentDetails.payment_mode; 584 if (paymentDetails.payment_method) eventData.payment_method = paymentDetails.payment_method; 585 586 console.log(`ð³ GTM VMA Login Fees (${eventData.event}):`, JSON.stringify(eventData, null, 2)); 587 window.dataLayer.push(eventData); 588} 589 590// VMA Processing Fees Payment Success/Failure tracking 591function trackVMAProcessingFeesPayment(eventType, customerID, paymentDetails = {}) { 592 const isSuccess = eventType === 'success'; 593 594 const eventData = { 595 event: isSuccess ? 'vma_processingfees_success' : 'vma_processingfees_failure', 596 event_name: isSuccess ? 'vma_processingfees_success' : 'vma_processingfees_failure', 597 step_name: isSuccess ? 'success' : 'failure', 598 login_status: loginInfo.login_status, 599 journey_name: getJourneyName().toLowerCase(), 600 customerID: loginInfo.customerID || hashCustomerID(customerID) 601 }; 602 603 if (paymentDetails.transactionID) eventData.transactionID = paymentDetails.transactionID; 604 if (paymentDetails.amount) eventData.amount = paymentDetails.amount; 605 if (paymentDetails.payment_mode) eventData.payment_mode = paymentDetails.payment_mode; 606 if (paymentDetails.payment_method) eventData.payment_method = paymentDetails.payment_method; 607 608 console.log(`ð³ GTM VMA Processing Fees (${eventData.event}):`, JSON.stringify(eventData, null, 2)); 609 window.dataLayer.push(eventData); 610} 611 612// Loan Service (LSP) journey analytics 613function trackLSPEvent(eventType, customerID, requestType = '') { 614 615 // Map event types to their configurations 616 const eventConfig = { 617 'ticket_submit_success': { 618 event: 'ticket_submit_success', 619 status: 'success' 620 }, 621 'ticket_submit_failure': { 622 event: 'ticket_submit_failure', 623 status: 'failure' 624 }, 625 'update_address_success': { 626 event: 'update_address_success', 627 eventName: 'update address success', 628 status: 'success' 629 }, 630 'update_address_failure': { 631 event: 'update_address_failure', 632 eventName: 'update address failure', 633 status: 'failure' 634 } 635 }; 636 637 const config = eventConfig[eventType]; 638 639 if (!config) { 640 console.error(`Unknown LSP event type: ${eventType}`); 641 return; 642 } 643 644 const eventData = { 645 event: config.event, 646 page_name: pageName, 647 request_status: config.status, 648 login_status: loginInfo.login_status, 649 journey_name: 'loan-service', 650 customerID: loginInfo.customerID || hashCustomerID(customerID) 651 }; 652 653 // Add event_name if defined 654 if (config.eventName) { 655 eventData.event_name = config.eventName; 656 } 657 658 if (eventType === 'ticket_submit_success' && requestType) { 659 eventData.request_type = requestType; 660 } 661 662 console.log(`ð GTM LSP Event (${config.event}):`, JSON.stringify(eventData, null, 2)); 663 window.dataLayer.push(eventData); 664} 665 666// Payment Success/Failure tracking 667function trackLSPPaymentEvent(eventType, customerID, paymentDetails = {}) { 668 const isSuccess = eventType === 'success'; 669 670 const eventData = { 671 event: isSuccess ? 'lsp_payment_success' : 'lsp_payment_failure', 672 event_name: isSuccess ? 'lsp_payment_success' : 'lsp_payment_failure', 673 step_name: isSuccess ? 'success' : 'failure', 674 request_status: isSuccess ? 'success' : 'failure', 675 login_status: loginInfo.login_status, 676 journey_name: getJourneyName().toLowerCase(), 677 customerID: loginInfo.customerID || hashCustomerID(customerID) 678 }; 679 680 if (paymentDetails.transactionID) eventData.transactionID = String(paymentDetails.transactionID); 681 if (paymentDetails.amount) eventData.amount = paymentDetails.amount; 682 if (paymentDetails.payment_mode) eventData.payment_mode = paymentDetails.payment_mode; 683 if (paymentDetails.payment_method) eventData.payment_method = paymentDetails.payment_method; 684 if (paymentDetails.request_type) eventData.request_type = paymentDetails.request_type; 685 686 console.log(`ð³ GTM LSP Payment (${eventData.event}):`, JSON.stringify(eventData, null, 2)); 687 window.dataLayer.push(eventData); 688} 689 690//Common otp succes,failure,resend analytics 691function trackOTPSuccess(customerID) { 692 const eventData = { 693 event: 'otp_success', 694 event_name: 'otp_sucess', 695 page_name: pageName, 696 journey_name: getJourneyName().toLowerCase(), 697 login_status: loginInfo.login_status, 698 customerID: loginInfo.customerID || hashCustomerID(customerID) 699 }; 700 701 console.log('ð GTM OTP success:', JSON.stringify(eventData, null, 2)); 702 window.dataLayer.push(eventData); 703} 704 705function trackOTPFailure(customerID) { 706 const eventData = { 707 event: 'otp_failure', 708 event_name: 'otp failure', 709 page_name: pageName, 710 journey_name: getJourneyName().toLowerCase(), 711 login_status: loginInfo.login_status, 712 customerID: loginInfo.customerID || hashCustomerID(customerID) 713 }; 714 715 console.log('ð GTM OTP failure:', JSON.stringify(eventData, null, 2)); 716 window.dataLayer.push(eventData); 717} 718 719function trackOTPResend(customerID) { 720 const eventData = { 721 event: 'otp_resend', 722 event_name: 'otp resend', 723 page_name: pageName, 724 journey_name: getJourneyName().toLowerCase(), 725 login_status: loginInfo.login_status, 726 customerID: loginInfo.customerID || hashCustomerID(customerID) 727 }; 728 729 console.log("ð GTM OTP resend:", JSON.stringify(eventData, null, 2)); 730 window.dataLayer.push(eventData); 731} 732 733//Common error tracking analytics 734function trackError(errorName, errorCode, customerID, journeyName) { 735 const eventData = { 736 event: 'error', 737 error_name: errorCode, 738 error_code: errorName.toLowerCase(), 739 page_name: pageName, 740 login_status: loginInfo.login_status, 741 journey_name: getJourneyName().toLowerCase() || journeyName, 742 customerID: loginInfo.customerID || hashCustomerID(customerID) 743 }; 744 745 console.log('â GTM error:', JSON.stringify(eventData, null, 2)); 746 window.dataLayer.push(eventData); 747} 748 749//commomn logic for login success 750function trackLoginSuccess(customerID, journeyName) { 751 const eventData = { 752 event: 'login_success', 753 event_name: 'login success', 754 link_pagename: pageName, 755 login_status: loginInfo.login_status, 756 journey_name: getJourneyName().toLowerCase() || journeyName.toLowerCase(), 757 customerID: loginInfo.customerID || hashCustomerID(customerID) 758 }; 759 760 console.log("ð GTM login success:", JSON.stringify(eventData, null, 2)); 761 window.dataLayer.push(eventData); 762} 763 764// Calculator apply_now / request_callback. `calculations` holds the 765// calculator-specific payload: emi_calculations, fd_calculations or pmay_calculations. 766function trackCalculatorEvent(eventName, calculatorName, calculations = {}) { 767 const eventData = { 768 event: eventName, 769 event_name: eventName, 770 link_pagename: pageName, 771 login_status: loginInfo.login_status, 772 journey_name: getJourneyName().toLowerCase(), 773 customerID: loginInfo.customerID, 774 calculator_name: String(calculatorName || '').toLowerCase(), 775 ...calculations, 776 }; 777 778 console.log(`ð§® GTM calculator (${eventName}):`, JSON.stringify(eventData, null, 2)); 779 window.dataLayer.push(eventData); 780} 781 782function trackCalculatorCategoryClick(ctaName) { 783 const eventData = { 784 event: 'click', 785 cta_name: String(ctaName || '').trim().toLowerCase(), 786 link_pagename: pageName, 787 login_status: loginInfo.login_status, 788 journey_name: getJourneyName().toLowerCase(), 789 customerID: loginInfo.customerID, 790 }; 791 792 console.log('ð§® GTM calculator category click:', JSON.stringify(eventData, null, 2)); 793 window.dataLayer.push(eventData); 794} 795 796// Export individual tracking functions for manual use 797export { trackClick, trackBannerClick, trackSearch, trackSearchResults, trackFileDownload, trackScroll, trackLoanAmountChange, trackFDTenureChange, trackFDJourneyEvent, trackApplyFDStep, trackOTPSuccess, trackOTPFailure, trackOTPResend, trackKYCVerifyStep, trackVMAEvent, trackLSPEvent, trackLoginSuccess, trackError, trackVMAFieldEntry, trackLoginFees, trackProcessingFees, trackLSPPaymentEvent, trackVMALoginFeesPayment, trackVMAProcessingFeesPayment, trackFormStart, trackFormSubmit, trackCalculatorEvent, trackCalculatorCategoryClick };
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.