@fynd-design-engineering/fynd-one-v2 2.2.11 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/debug.js +153 -1
- package/dist/analytics/form-success.js +74 -1
- package/dist/analytics/main.js +98 -1
- package/dist/analytics/main.js.map +2 -2
- package/dist/navigation/desktop/index.js.map +1 -1
- package/dist/posthog/main.js +1 -0
- package/dist/posthog/main.js.map +7 -0
- package/dist/tracking/form-tracker.js +1 -0
- package/dist/tracking/form-tracker.js.map +7 -0
- package/dist/tracking/user-journey.js +1 -1
- package/dist/tracking/user-journey.js.map +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{var a=()=>{let r=window.location.pathname,t={source_page:r==="/"?`${r} Home`:r,fynd_product:"fynd.com website",interface:"Webflow",device_type:/Mobile|Android|iPhone|iPad/.test(navigator.userAgent)?"Mobile":"Web",utm_source:new URLSearchParams(window.location.search).get("utm_source")||"",utm_medium:new URLSearchParams(window.location.search).get("utm_medium")||"",utm_campaign:new URLSearchParams(window.location.search).get("utm_campaign")||"",referrer:document.referrer};try{let e=null;if(typeof window.getUserJourney=="function"&&(e=window.getUserJourney()),!e){let n=sessionStorage.getItem("userJourney");n&&(e=JSON.parse(n))}if(e){if(t.user_journey=e,e.formDetails){let n=e.formDetails;n.formId&&(t.form_id=n.formId),n.formName&&(t.form_name=n.formName),n.firstName&&(t.form_first_name=n.firstName),n.lastName&&(t.form_last_name=n.lastName),n.email&&(t.form_email=n.email),n.phone&&(t.form_phone=n.phone)}if(e.userJourney&&e.userJourney.length>0){t.journey_total_pages=e.userJourney.length,t.journey_first_page=e.userJourney[0].page,t.journey_current_page=e.userJourney[e.userJourney.length-1].page;let n=new Date(e.userJourney[0].time),s=new Date(e.userJourney[e.userJourney.length-1].time);t.journey_session_duration=Math.floor((s.getTime()-n.getTime())/1e3)}e.deviceCategory&&(t.journey_device_category=e.deviceCategory),e.browser&&(t.journey_browser=e.browser),e.origin&&(t.journey_origin=e.origin)}}catch(e){console.warn("Error getting user journey data for tracking:",e)}return t},i=(r,t)=>{try{let e=a(),n=t?{...e,...t}:e;window.posthog&&window.posthog.capture(r,n)}catch(e){console.error("Error tracking event:",e)}},u=r=>{let t=r.closest("form");return t&&(t.getAttribute("data-name")||t.getAttribute("name")||t.id)||null};document.addEventListener("DOMContentLoaded",function(){let r=a();window.posthog&&window.posthog.capture("$pageview",r)});window.addEventListener("load",function(){i("fynd_page_loaded"),m()});function m(){if(window.location.pathname==="/thank-you"){let t=performance.getEntriesByType("navigation");t.length>0&&(t[0].type==="reload"||document.referrer&&new URL(document.referrer).origin===window.location.origin)&&setTimeout(()=>{i("fynd_form_success")},200)}}document.addEventListener("DOMContentLoaded",function(){let r=document.querySelectorAll('[data-ph="sign-up"]'),t=document.querySelectorAll('[data-ph="sign-in"]'),e=document.querySelectorAll('[href="#footer-form"]'),n=document.querySelectorAll('[data-ph="book-a-demo"]');document.querySelectorAll('[type="submit"]').forEach(o=>{o.addEventListener("click",function(){let c=u(this);setTimeout(()=>{window.validationPassed===!0&&i("fynd_form_submitted",c?{submitted_form:c}:{})},100)})}),r.forEach(o=>{o.addEventListener("click",function(){i("fynd_clicked_sign_up")})}),t.forEach(o=>{o.addEventListener("click",function(){i("fynd_clicked_sign_in")})}),e.forEach(o=>{o.addEventListener("click",function(){i("fynd_clicked_scroll_to_form")})}),n.forEach(o=>{o.addEventListener("click",function(){i("fynd_clicked_book_a_demo")})})});window.getPosthogTrackingProperties=a;window.trackEvent=i;})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/posthog/main.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// trackingIntegration.ts - PostHog tracking with user journey integration\nimport { FormDetails } from '../utils/types/user-journey';\n\n// Define tracking properties interface\ninterface TrackingProperties {\n source_page: string;\n fynd_product: string;\n interface: string;\n device_type: string;\n utm_source: string;\n utm_medium: string;\n utm_campaign: string;\n referrer: string;\n // Form details from user journey\n form_id?: string;\n form_name?: string;\n form_first_name?: string;\n form_last_name?: string;\n form_email?: string;\n form_phone?: string;\n // User journey details\n journey_total_pages?: number;\n journey_session_duration?: number;\n journey_first_page?: string;\n journey_current_page?: string;\n journey_device_category?: string;\n journey_browser?: string;\n journey_origin?: string;\n // Complete user journey data\n user_journey?: any; // Array of touchpoints from userJourney field\n // Additional event-specific properties\n submitted_form?: string;\n [key: string]: any; // Allow additional properties\n}\n\ndeclare global {\n interface Window {\n trackEvent: (eventName: string, properties?: Partial<TrackingProperties>) => void;\n getPosthogTrackingProperties: () => TrackingProperties;\n }\n}\n\n// Enhanced tracking properties function\nconst getPosthogTrackingProperties = (): TrackingProperties => {\n const pathname: string = window.location.pathname;\n\n // Base tracking properties\n const baseProperties: TrackingProperties = {\n source_page: pathname === \"/\" ? `${pathname} Home` : pathname,\n fynd_product: \"fynd.com website\",\n interface: \"Webflow\",\n device_type: /Mobile|Android|iPhone|iPad/.test(navigator.userAgent)\n ? \"Mobile\"\n : \"Web\",\n utm_source:\n new URLSearchParams(window.location.search).get(\"utm_source\") || \"\",\n utm_medium:\n new URLSearchParams(window.location.search).get(\"utm_medium\") || \"\",\n utm_campaign:\n new URLSearchParams(window.location.search).get(\"utm_campaign\") || \"\",\n referrer: document.referrer,\n };\n\n // Get user journey data if available\n try {\n // Try to get from getUserJourney function first\n let journey = null;\n if (typeof (window as any).getUserJourney === 'function') {\n journey = (window as any).getUserJourney();\n journey = journey.userJourney || journey;\n }\n\n // If not available from function, try to get directly from sessionStorage\n if (!journey) {\n const storedData = sessionStorage.getItem('userJourney');\n if (storedData) {\n journey = JSON.parse(storedData);\n }\n }\n\n if (journey) {\n // Add the complete user journey object\n baseProperties.user_journey = journey;\n\n // Add form details if available\n if (journey.formDetails) {\n const formDetails: FormDetails = journey.formDetails;\n\n // Only add form properties if they have values\n if (formDetails.formId) {\n baseProperties.form_id = formDetails.formId;\n }\n if (formDetails.formName) {\n baseProperties.form_name = formDetails.formName;\n }\n if (formDetails.firstName) {\n baseProperties.form_first_name = formDetails.firstName;\n }\n if (formDetails.lastName) {\n baseProperties.form_last_name = formDetails.lastName;\n }\n if (formDetails.email) {\n baseProperties.form_email = formDetails.email;\n }\n if (formDetails.phone) {\n baseProperties.form_phone = formDetails.phone;\n }\n }\n\n // Add journey metadata\n if (journey.userJourney && journey.userJourney.length > 0) {\n baseProperties.journey_total_pages = journey.userJourney.length;\n baseProperties.journey_first_page = journey.userJourney[0].page;\n baseProperties.journey_current_page = journey.userJourney[journey.userJourney.length - 1].page;\n\n // Calculate session duration\n const firstVisit = new Date(journey.userJourney[0].time);\n const lastVisit = new Date(journey.userJourney[journey.userJourney.length - 1].time);\n baseProperties.journey_session_duration = Math.floor((lastVisit.getTime() - firstVisit.getTime()) / 1000);\n }\n\n // Add device and browser info from journey\n if (journey.deviceCategory) {\n baseProperties.journey_device_category = journey.deviceCategory;\n }\n if (journey.browser) {\n baseProperties.journey_browser = journey.browser;\n }\n if (journey.origin) {\n baseProperties.journey_origin = journey.origin;\n }\n }\n } catch (error) {\n console.warn('Error getting user journey data for tracking:', error);\n }\n\n return baseProperties;\n};\n\n// Track event function\nconst trackEvent = (eventName: string, properties?: Partial<TrackingProperties>): void => {\n try {\n const trackingProps = getPosthogTrackingProperties();\n\n // Merge with additional properties if provided\n const finalProperties = properties ? { ...trackingProps, ...properties } : trackingProps;\n\n // Track with PostHog if available\n if ((window as any).posthog) {\n (window as any).posthog.capture(eventName, finalProperties);\n }\n\n // Optional: Console log for debugging (remove in production)\n // console.log('Tracked event:', eventName, finalProperties);\n } catch (error) {\n console.error('Error tracking event:', error);\n }\n};\n\n// Helper function to get parent form name\nconst getParentFormName = (element: HTMLElement): string | null => {\n const parentForm = element.closest(\"form\") as HTMLFormElement | null;\n if (parentForm) {\n return parentForm.getAttribute(\"data-name\") ||\n parentForm.getAttribute(\"name\") ||\n parentForm.id ||\n null;\n }\n return null;\n};\n\n// Initialize PostHog pageview\ndocument.addEventListener(\"DOMContentLoaded\", function (): void {\n const trackingProps = getPosthogTrackingProperties();\n\n // PostHog pageview\n if ((window as any).posthog) {\n (window as any).posthog.capture(\"$pageview\", trackingProps);\n }\n});\n\n// Track page load event\nwindow.addEventListener(\"load\", function (): void {\n trackEvent(\"fynd_page_loaded\");\n\n // Check if this is the thank you page and trigger form success event\n checkThankYouPageEvent();\n});\n\n// Function to check and trigger thank you page event\nfunction checkThankYouPageEvent(): void {\n const currentPath = window.location.pathname;\n\n // Check if current page is thank you page\n if (currentPath === '/thank-you') {\n // Check if this is a page reload (not initial navigation)\n const navigationEntries = performance.getEntriesByType('navigation');\n if (navigationEntries.length > 0) {\n const navEntry = navigationEntries[0] as PerformanceNavigationTiming;\n\n // Check if it's a reload (type === 'reload') or if there's a referrer from the same origin\n const isReload = navEntry.type === 'reload' ||\n (document.referrer && new URL(document.referrer).origin === window.location.origin);\n\n if (isReload) {\n // Trigger event after 200ms delay\n setTimeout(() => {\n trackEvent(\"fynd_form_success\");\n }, 200);\n }\n }\n }\n}\n\n// Button click tracking for sign up, sign in, scroll to form and book a demo buttons\ndocument.addEventListener(\"DOMContentLoaded\", function (): void {\n const signUpButtons = document.querySelectorAll('[data-ph=\"sign-up\"]') as NodeListOf<Element>;\n const signInButtons = document.querySelectorAll('[data-ph=\"sign-in\"]') as NodeListOf<Element>;\n const scrollToFormButtons = document.querySelectorAll(\n '[href=\"#footer-form\"]'\n ) as NodeListOf<Element>;\n const bookADemoButtons = document.querySelectorAll('[data-ph=\"book-a-demo\"]') as NodeListOf<Element>;\n const submitButtons = document.querySelectorAll('[type=\"submit\"]') as NodeListOf<Element>;\n\n submitButtons.forEach((button: Element) => {\n button.addEventListener(\"click\", function (this: HTMLElement): void {\n const formName = getParentFormName(this);\n setTimeout(() => {\n if (window.validationPassed === true) {\n // If validation passed, track the submit event\n // Additional properties can be added here if needed\n const additionalProps = formName ? { submitted_form: formName } : {};\n trackEvent(\"fynd_form_submitted\", additionalProps);\n }\n }, 100);\n });\n });\n\n signUpButtons.forEach((button: Element) => {\n button.addEventListener(\"click\", function (): void {\n trackEvent(\"fynd_clicked_sign_up\");\n });\n });\n\n signInButtons.forEach((button: Element) => {\n button.addEventListener(\"click\", function (): void {\n trackEvent(\"fynd_clicked_sign_in\");\n });\n });\n\n scrollToFormButtons.forEach((button: Element) => {\n button.addEventListener(\"click\", function (): void {\n trackEvent(\"fynd_clicked_scroll_to_form\");\n });\n });\n\n bookADemoButtons.forEach((button: Element) => {\n button.addEventListener(\"click\", function (): void {\n trackEvent(\"fynd_clicked_book_a_demo\");\n });\n });\n});\n\n// Make functions globally accessible\nwindow.getPosthogTrackingProperties = getPosthogTrackingProperties;\nwindow.trackEvent = trackEvent;\n\n// Export for module usage\nexport {\n getPosthogTrackingProperties,\n trackEvent,\n getParentFormName,\n type TrackingProperties\n};"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{var o=class{constructor(){this.processedForms=new Set;this.formFieldMap=new Map([["firstName","firstName"],["first_name","firstName"],["fname","firstName"],["lastName","lastName"],["last_name","lastName"],["lname","lastName"],["email","email"],["email_address","email"],["phone","phone"],["phone_number","phone"],["mobile","phone"],["tel","phone"]]);this.init()}init(){document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.setupFormTracking()):this.setupFormTracking()}setupFormTracking(){document.querySelectorAll("[data-posthog-trigger]").forEach(t=>{t.addEventListener("change",r=>{this.handleFormInteraction(r)}),t.addEventListener("input",r=>{this.handleFormInput(r)})})}handleFormInteraction(e){let r=e.target.closest("form");if(console.log("Form interaction detected:",r),!r||this.processedForms.has(r))return null;this.processedForms.add(r);let a=r.getAttribute("data-name"),n=r.getAttribute("id")||this.generateFormId(r);return a?(window.interactedForm=a,this.updateUserJourneyFormDetails(n,a),typeof window.getTrackingPropertiesWithForm=="function"&&typeof window.trackEvent=="function"&&window.trackEvent("fynd_form_started",window.getTrackingPropertiesWithForm(a)),a):null}handleFormInput(e){let t=e.target,r=this.getFieldName(t),a=this.mapFieldName(r);a&&this.updateUserJourneyFormData(a,t.value)}getFieldName(e){return e.getAttribute("name")||e.getAttribute("data-field")||e.getAttribute("data-name")||e.getAttribute("id")||""}mapFieldName(e){let t=e.toLowerCase();if(this.formFieldMap.has(t))return this.formFieldMap.get(t);for(let[r,a]of this.formFieldMap.entries())if(t.includes(r))return a;return null}generateFormId(e){let t=e.getAttribute("data-name")||"unknown",r=Date.now();return`form-${t}-${r}`}updateUserJourneyFormDetails(e,t){typeof window.setFormDetails=="function"&&window.setFormDetails(e,t)}updateUserJourneyFormData(e,t){typeof window.setFormData=="function"&&window.setFormData(e,t)}addFieldMapping(e,t){this.formFieldMap.set(e.toLowerCase(),t)}reinitialize(){this.processedForms.clear(),this.setupFormTracking(),typeof window.reinitializeFormTracking=="function"&&window.reinitializeFormTracking()}getFormData(){if(typeof window.getUserJourney=="function"){let e=window.getUserJourney();return e?e.formDetails:null}return null}setFormData(e,t){return this.updateUserJourneyFormData(e,t)!==void 0}isFormInteracted(e){return this.processedForms.has(e)}},i=new o;window.formTracker=i;var m=i;})();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../bin/live-reload.js", "../../src/tracking/form-tracker.ts"],
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// formTracker.ts - Form tracking integration with user journey\nimport { FormDetails } from './types';\n\n// Extend existing window interface instead of redeclaring\ndeclare global {\n interface Window {\n interactedForm: string;\n formTracker: FormTracker;\n }\n}\n\n// Form tracking functionality\nclass FormTracker {\n private processedForms: Set<HTMLFormElement> = new Set();\n private formFieldMap: Map<string, keyof FormDetails> = new Map<string, keyof FormDetails>([\n ['firstName', 'firstName' as keyof FormDetails],\n ['first_name', 'firstName' as keyof FormDetails],\n ['fname', 'firstName' as keyof FormDetails],\n ['lastName', 'lastName' as keyof FormDetails],\n ['last_name', 'lastName' as keyof FormDetails],\n ['lname', 'lastName' as keyof FormDetails],\n ['email', 'email' as keyof FormDetails],\n ['email_address', 'email' as keyof FormDetails],\n ['phone', 'phone' as keyof FormDetails],\n ['phone_number', 'phone' as keyof FormDetails],\n ['mobile', 'phone' as keyof FormDetails],\n ['tel', 'phone' as keyof FormDetails]\n ]);\n\n constructor() {\n this.init();\n }\n\n private init(): void {\n // Initialize when DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => this.setupFormTracking());\n } else {\n this.setupFormTracking();\n }\n }\n\n private setupFormTracking(): void {\n // Select all form fields with data-posthog-trigger attribute\n const formFields = document.querySelectorAll(\"[data-posthog-trigger]\") as NodeListOf<Element>;\n\n formFields.forEach((field: Element) => {\n // Add change event listener for form interaction tracking\n field.addEventListener(\"change\", (event: Event) => {\n this.handleFormInteraction(event);\n });\n\n // Add input event listener for real-time form data tracking\n field.addEventListener(\"input\", (event: Event) => {\n this.handleFormInput(event);\n });\n });\n }\n\n private handleFormInteraction(event: Event): string | null {\n const field = event.target as Element;\n const parentForm = field.closest(\"form\") as HTMLFormElement | null;\n console.log(\"Form interaction detected:\", parentForm);\n\n if (!parentForm) return null;\n\n // Check if this form has already been processed for interaction\n if (this.processedForms.has(parentForm)) {\n return null;\n }\n\n // Mark this form as processed\n this.processedForms.add(parentForm);\n\n // Get the data-name attribute value from the parent form\n const formName = parentForm.getAttribute(\"data-name\");\n const formId = parentForm.getAttribute(\"id\") || this.generateFormId(parentForm);\n\n if (formName) {\n // Update global interacted form\n window.interactedForm = formName;\n\n // Update user journey form details\n this.updateUserJourneyFormDetails(formId, formName);\n\n // Track form started event (if trackEvent function exists)\n if (typeof (window as any).getTrackingPropertiesWithForm === 'function') {\n // Assuming trackEvent function exists globally\n if (typeof (window as any).trackEvent === 'function') {\n (window as any).trackEvent(\n \"fynd_form_started\",\n (window as any).getTrackingPropertiesWithForm(formName)\n );\n }\n }\n\n return formName;\n }\n\n return null;\n }\n\n private handleFormInput(event: Event): void {\n const field = event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n const fieldName = this.getFieldName(field);\n const mappedFieldName = this.mapFieldName(fieldName);\n\n if (!mappedFieldName) return;\n\n // Update user journey form data\n this.updateUserJourneyFormData(mappedFieldName, field.value);\n }\n\n private getFieldName(field: HTMLElement): string {\n // Try to get field name from various attributes\n return field.getAttribute('name') ||\n field.getAttribute('data-field') ||\n field.getAttribute('data-name') ||\n field.getAttribute('id') ||\n '';\n }\n\n private mapFieldName(fieldName: string): keyof FormDetails | null {\n // Convert field name to lowercase for comparison\n const lowerFieldName = fieldName.toLowerCase();\n\n // Check if we have a mapping for this field\n if (this.formFieldMap.has(lowerFieldName)) {\n return this.formFieldMap.get(lowerFieldName)!;\n }\n\n // Check if the field name contains any of our mapped fields\n for (const [key, mappedField] of this.formFieldMap.entries()) {\n if (lowerFieldName.includes(key)) {\n return mappedField;\n }\n }\n\n return null;\n }\n\n private generateFormId(form: HTMLFormElement): string {\n // Generate a unique form ID based on form attributes\n const formName = form.getAttribute(\"data-name\") || 'unknown';\n const timestamp = Date.now();\n return `form-${formName}-${timestamp}`;\n }\n\n private updateUserJourneyFormDetails(formId: string, formName: string): void {\n if (typeof (window as any).setFormDetails === 'function') {\n (window as any).setFormDetails(formId, formName);\n }\n }\n\n private updateUserJourneyFormData(fieldName: keyof FormDetails, value: string): void {\n if (typeof (window as any).setFormData === 'function') {\n (window as any).setFormData(fieldName, value);\n }\n }\n\n // Public method to add custom field mapping\n public addFieldMapping(fieldName: string, mappedField: keyof FormDetails): void {\n this.formFieldMap.set(fieldName.toLowerCase(), mappedField);\n }\n\n // Public method to reinitialize tracking (useful for dynamic content)\n public reinitialize(): void {\n this.processedForms.clear();\n this.setupFormTracking();\n\n // Also reinitialize the user journey form tracking\n if (typeof (window as any).reinitializeFormTracking === 'function') {\n (window as any).reinitializeFormTracking();\n }\n }\n\n // Public method to get current form data\n public getFormData(): FormDetails | null {\n if (typeof (window as any).getUserJourney === 'function') {\n const journey = (window as any).getUserJourney();\n return journey ? journey.formDetails : null;\n }\n return null;\n }\n\n // Public method to manually set form data\n public setFormData(fieldName: keyof FormDetails, value: string): boolean {\n return this.updateUserJourneyFormData(fieldName, value) !== undefined;\n }\n\n // Public method to check if a form has been interacted with\n public isFormInteracted(form: HTMLFormElement): boolean {\n return this.processedForms.has(form);\n }\n}\n\n// Initialize the form tracker\nconst formTracker = new FormTracker();\n\n// Make form tracker globally accessible\nwindow.formTracker = formTracker;\n\n// Export for module usage\nexport { FormTracker };\nexport default formTracker;"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{async function
|
|
1
|
+
"use strict";(()=>{async function f(){let e="userJourney";function t(){let n=navigator.userAgent;return/tablet|ipad|playbook|silk/i.test(n)?"tablet":/mobile|iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(n)?"mobile":"desktop"}function a(){let n=navigator.userAgent;return n.includes("Chrome")&&!n.includes("Edg")?"Chrome":n.includes("Firefox")?"Firefox":n.includes("Safari")&&!n.includes("Chrome")?"Safari":n.includes("Edg")?"Edge":n.includes("Opera")?"Opera":"Unknown"}function s(n){if(!n)return"Unknown";try{let u=new URL(n).hostname.replace(/^www\./,""),m=u.split(".");return m.length>=2?m[0]:u||"Unknown"}catch{return"Unknown"}}function d(n,o){let i=new URLSearchParams(window.location.search),u=i.has("utm_source")||i.has("utm_medium")||i.has("utm_campaign");return n||u?u?{source:i.get("utm_source")||"",medium:i.get("utm_medium")||"",campaign:i.get("utm_campaign")||""}:{source:s(document.referrer),medium:"organic",campaign:"unknown"}:o||{source:"Unknown",medium:"organic",campaign:"unknown"}}function h(){try{return typeof window.pageCategories<"u"&&Array.isArray(window.pageCategories)&&window.pageCategories.length>0?window.pageCategories:["Not applicable"]}catch(n){return console.warn("Error accessing pageCategories:",n),["Not applicable"]}}function w(){let n=new URLSearchParams(window.location.search);return n.has("utm_source")||n.has("utm_medium")||n.has("utm_campaign")}function J(n){let o=n.split("?")[0].toLowerCase(),i={exactMatches:{"/":"Home","/home":"Home","/blog":"Blog listing","/about-us":"About us","/contact-us":"Contact","/privacy-policy":"Privacy policy","/terms-of-service":"Terms of service","/careers":"Careers","/customer-stories":"Customer stories listing","/events":"Events listing","/infographics":"Infographics listing","/newsroom":"Newsroom","/releases":"Releases listing"},pathStartsWith:[{pattern:"/blog/",type:"Blog"},{pattern:"/customer-stories/",type:"Customer story"},{pattern:"/case-studies/",type:"Case study"},{pattern:"/solutions/",type:"Solution"},{pattern:"/events/",type:"Event"},{pattern:"/news/",type:"News"},{pattern:"/press-releases/",type:"Press release"},{pattern:"/releases/",type:"Release"}]};if(i.exactMatches[o])return i.exactMatches[o];for(let u of i.pathStartsWith)if(o.startsWith(u.pattern))return u.type;return"Other"}function D(n){if(!n.userJourney||n.userJourney.length===0)return!1;let o=new Date(n.userJourney[n.userJourney.length-1].time);return new Date().getTime()-o.getTime()<18e5}return new Promise(n=>{setTimeout(()=>{try{let o=null,i=sessionStorage.getItem(e);if(i){let c=JSON.parse(i);D(c)&&(o=c)}o||(o={userJourney:[],origin:window.location.hostname,deviceCategory:t(),browser:a(),formDetails:{formId:"",formName:"",firstName:"",lastName:"",email:"",phone:""}}),o.formDetails||(o.formDetails={formId:"",formName:"",firstName:"",lastName:"",email:"",phone:""});let u=window.location.pathname,m=new Date().toISOString(),y=o.userJourney[o.userJourney.length-1];if(y&&y.page===u)y.time=m;else{let c=o.userJourney.length===0,S=c?void 0:o.userJourney[0].utm,b={touchPoint:o.userJourney.length+1,page:u,title:document.title||"Untitled",type:J(u),category:h(),time:m,utmVisibility:w()?"visible":"hidden",utm:d(c,S)};o.userJourney.push(b)}sessionStorage.setItem(e,JSON.stringify(o)),p(),n(o)}catch(o){console.error("Error tracking user journey:",o),n(null)}},200)})}function p(){document.querySelectorAll("input[ph-form-field], textarea[ph-form-field], select[ph-form-field]").forEach(t=>{t.removeEventListener("input",g),t.removeEventListener("change",g)}),document.querySelectorAll("input[ph-form-field], textarea[ph-form-field], select[ph-form-field]").forEach(t=>{t.addEventListener("input",g),t.addEventListener("change",g)}),U()}function U(){let e=l();if(!e)return;let r=document.querySelector("[ph-form-name]");if(!r)return;let t=r.getAttribute("ph-form-name"),a=r.getAttribute("ph-form-id")||"form-1";t&&(e.formDetails.formName||(e.formDetails.formId=a,e.formDetails.formName=t),sessionStorage.setItem("userJourney",JSON.stringify(e)))}function g(e){let r=e.target,t=r.getAttribute("ph-form-field");if(!t)return;let a=r.closest("[ph-form-name]");if(!a)return;let s=a.getAttribute("ph-form-name"),d=a.getAttribute("ph-form-id")||"form-1";s&&T(s,d,t,r.value)}function T(e,r,t,a){try{let s=l();if(!s)return!1;switch(s.formDetails.formId=r,s.formDetails.formName=e,t){case"firstName":s.formDetails.firstName=a;break;case"lastName":s.formDetails.lastName=a;break;case"email":s.formDetails.email=a;break;case"phone":s.formDetails.phone=a;break;default:return console.warn(`Unknown field: ${t}`),!1}return sessionStorage.setItem("userJourney",JSON.stringify(s)),!0}catch(s){return console.error("Error updating form data:",s),!1}}function l(){try{let e=sessionStorage.getItem("userJourney");return e?JSON.parse(e):null}catch(e){return console.error("Error getting user journey:",e),null}}function P(){sessionStorage.removeItem("userJourney")}function F(e){try{let r=l();if(!r||r.userJourney.length===0)return!1;let t=r.userJourney[r.userJourney.length-1];return t.category=e.length>0?e:["Not applicable"],sessionStorage.setItem("userJourney",JSON.stringify(r)),!0}catch(r){return console.error("Error updating page categories:",r),!1}}function N(e){try{let r=l();if(!r||r.userJourney.length===0)return!1;let t=r.userJourney[r.userJourney.length-1];return t.type=e,sessionStorage.setItem("userJourney",JSON.stringify(r)),!0}catch(r){return console.error("Error updating page type:",r),!1}}function k(){let e=l();if(!e||e.userJourney.length===0)return null;let r=e.userJourney[0],t=e.userJourney[e.userJourney.length-1],a=new Date(t.time).getTime()-new Date(r.time).getTime();return{totalPages:e.userJourney.length,sessionDuration:Math.floor(a/1e3),firstPage:r.page,lastPage:t.page}}function v(){let e=l();return e?e.formDetails:null}function E(e){let r=l();return r&&r.formDetails[e]||null}function C(e,r){try{let t=l();return t?(t.formDetails[e]=r,sessionStorage.setItem("userJourney",JSON.stringify(t)),!0):!1}catch(t){return console.error("Error setting form data:",t),!1}}function I(e,r){try{let t=l();return t?(t.formDetails.formId=e,t.formDetails.formName=r,sessionStorage.setItem("userJourney",JSON.stringify(t)),!0):!1}catch(t){return console.error("Error setting form details:",t),!1}}function M(){p()}document.addEventListener("DOMContentLoaded",()=>{f()});document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{f()}):f();window.trackUserJourney=f;window.getUserJourney=l;window.clearUserJourney=P;window.updatePageType=N;window.updatePageCategories=F;window.getJourneyStats=k;window.getFormData=v;window.getFormFieldValue=E;window.setFormData=C;window.setFormDetails=I;window.reinitializeFormTracking=M;})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../bin/live-reload.js", "../../src/tracking/user-journey.ts"],
|
|
4
|
-
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// userJourney.ts - Main tracking functionality with form details\nimport {\n UTMParameters,\n TouchPoint,\n UserJourney,\n DeviceCategory,\n UTMVisibility,\n JourneyStats,\n FormDetails,\n FormData\n} from './types';\n\nexport { };\n\nasync function trackUserJourney(): Promise<UserJourney | null> {\n const STORAGE_KEY: string = 'userJourney';\n const SESSION_TIMEOUT: number = 30 * 60 * 1000; // 30 minutes\n\n // Helper function to get device category\n function getDeviceCategory(): DeviceCategory {\n const userAgent: string = navigator.userAgent;\n if (/tablet|ipad|playbook|silk/i.test(userAgent)) return 'tablet';\n if (/mobile|iphone|ipod|android|blackberry|opera|mini|windows\\sce|palm|smartphone|iemobile/i.test(userAgent)) return 'mobile';\n return 'desktop';\n }\n\n // Helper function to get browser\n function getBrowser(): string {\n const userAgent: string = navigator.userAgent;\n if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) return 'Chrome';\n if (userAgent.includes('Firefox')) return 'Firefox';\n if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) return 'Safari';\n if (userAgent.includes('Edg')) return 'Edge';\n if (userAgent.includes('Opera')) return 'Opera';\n return 'Unknown';\n }\n\n // Helper function to extract domain from referrer\n function extractDomainFromReferrer(referrer: string): string {\n if (!referrer) return 'Unknown';\n\n try {\n const url = new URL(referrer);\n const hostname = url.hostname;\n\n // Remove www. prefix if present\n const domain = hostname.replace(/^www\\./, '');\n\n // Extract the main domain name (remove TLD)\n const domainParts = domain.split('.');\n if (domainParts.length >= 2) {\n return domainParts[0];\n }\n\n return domain || 'Unknown';\n } catch (error) {\n return 'Unknown';\n }\n }\n\n // Helper function to get UTM parameters\n function getUTMParameters(isFirstVisit: boolean, firstVisitUTM?: UTMParameters): UTMParameters {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n const hasCurrentUTM: boolean = urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n\n if (isFirstVisit || hasCurrentUTM) {\n // If UTM parameters are present in URL, use them\n if (hasCurrentUTM) {\n return {\n source: urlParams.get('utm_source') || '',\n medium: urlParams.get('utm_medium') || '',\n campaign: urlParams.get('utm_campaign') || ''\n };\n } else {\n // No UTM parameters in URL, use referrer-based defaults\n const referrerDomain = extractDomainFromReferrer(document.referrer);\n return {\n source: referrerDomain,\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n } else {\n // Inherit from first visit\n return firstVisitUTM || {\n source: 'Unknown',\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n }\n\n // Helper function to get page categories from global variable\n function getPageCategories(): string[] {\n try {\n // Check if global pageCategories variable exists and is an array\n if (typeof (window as any).pageCategories !== 'undefined' &&\n Array.isArray((window as any).pageCategories) &&\n (window as any).pageCategories.length > 0) {\n return (window as any).pageCategories;\n }\n\n // Return default if not available or empty\n return ['Not applicable'];\n } catch (error) {\n console.warn('Error accessing pageCategories:', error);\n return ['Not applicable'];\n }\n }\n\n function hasVisibleUTM(): boolean {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n return urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n }\n\n // Helper function to get page type (customize as needed)\n function getPageType(url: string): string {\n const path: string = url.split('?')[0].toLowerCase();\n\n // Type configuration - easy to maintain and extend\n const typeConfig = {\n // Exact path matches (highest priority)\n exactMatches: {\n '/': 'Home',\n '/home': 'Home',\n '/blog': 'Blog listing',\n '/about-us': 'About us',\n '/contact-us': 'Contact',\n '/privacy-policy': 'Privacy policy',\n '/terms-of-service': 'Terms of service',\n '/careers': 'Careers',\n '/customer-stories': 'Customer stories listing',\n '/events': 'Events listing',\n '/infographics': 'Infographics listing',\n '/newsroom': 'Newsroom',\n '/releases': 'Releases listing',\n } as Record<string, string>,\n\n // Path pattern matches\n // These will match if the path starts with the pattern\n pathStartsWith: [\n { pattern: '/blog/', type: 'Blog' },\n { pattern: '/customer-stories/', type: 'Customer story' },\n { pattern: '/case-studies/', type: 'Case study' },\n { pattern: '/solutions/', type: 'Solution' },\n { pattern: '/events/', type: 'Event' },\n { pattern: '/news/', type: 'News' },\n { pattern: '/press-releases/', type: 'Press release' },\n { pattern: '/releases/', type: 'Release' },\n ]\n };\n\n // 1. Check exact matches first\n if (typeConfig.exactMatches[path]) {\n return typeConfig.exactMatches[path];\n }\n\n // 2. Check path starts with patterns\n for (const item of typeConfig.pathStartsWith) {\n if (path.startsWith(item.pattern)) {\n return item.type;\n }\n }\n\n // 3. Default fallback\n return 'Other';\n }\n\n // Check if session is still valid\n function isValidSession(journey: UserJourney): boolean {\n if (!journey.userJourney || journey.userJourney.length === 0) return false;\n\n const lastVisit: Date = new Date(journey.userJourney[journey.userJourney.length - 1].time);\n const now: Date = new Date();\n\n return (now.getTime() - lastVisit.getTime()) < SESSION_TIMEOUT;\n }\n\n // Add 200ms delay before executing the main logic\n return new Promise((resolve) => {\n setTimeout(() => {\n try {\n // Get existing journey from sessionStorage\n let journey: UserJourney | null = null;\n const storedData: string | null = sessionStorage.getItem(STORAGE_KEY);\n\n if (storedData) {\n const parsedData: UserJourney = JSON.parse(storedData);\n\n // Check if session is still valid\n if (isValidSession(parsedData)) {\n journey = parsedData;\n }\n }\n\n // Initialize new journey if none exists or session expired\n if (!journey) {\n journey = {\n userJourney: [],\n origin: window.location.hostname,\n deviceCategory: getDeviceCategory(),\n browser: getBrowser(),\n formDetails: []\n };\n }\n\n // Ensure formDetails exists for backward compatibility\n if (!journey.formDetails) {\n journey.formDetails = [];\n }\n\n // Get current page info\n const currentUrl: string = window.location.pathname;\n const currentTime: string = new Date().toISOString();\n\n // Check if this is the same page as the last visit (avoid duplicates)\n const lastVisit: TouchPoint | undefined = journey.userJourney[journey.userJourney.length - 1];\n if (lastVisit && lastVisit.page === currentUrl) {\n // Same page, just update the time\n lastVisit.time = currentTime;\n } else {\n // New page visit\n const isFirstVisit: boolean = journey.userJourney.length === 0;\n const firstVisitUTM: UTMParameters | undefined = isFirstVisit ? undefined : journey.userJourney[0].utm;\n\n const touchPoint: TouchPoint = {\n touchPoint: journey.userJourney.length + 1,\n page: currentUrl,\n title: document.title || 'Untitled',\n type: getPageType(currentUrl),\n category: getPageCategories(),\n time: currentTime,\n utmVisibility: hasVisibleUTM() ? 'visible' : 'hidden',\n utm: getUTMParameters(isFirstVisit, firstVisitUTM)\n };\n\n journey.userJourney.push(touchPoint);\n }\n\n // Save updated journey to sessionStorage\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify(journey));\n\n // Initialize form tracking\n initializeFormTracking();\n\n // // Optional: Log for debugging\n // console.log('User journey updated:', journey);\n\n resolve(journey);\n\n } catch (error: unknown) {\n console.error('Error tracking user journey:', error);\n resolve(null);\n }\n }, 200); // 200ms delay\n });\n}\n\n// Form tracking functionality\nfunction initializeFormTracking(): void {\n // Remove existing event listeners to prevent duplicates\n const existingInputs = document.querySelectorAll('input[ph-form-field], textarea[ph-form-field], select[ph-form-field]');\n existingInputs.forEach(input => {\n input.removeEventListener('input', handleFormFieldChange);\n input.removeEventListener('change', handleFormFieldChange);\n });\n\n // Add event listeners to form fields\n const formFields = document.querySelectorAll('input[ph-form-field], textarea[ph-form-field], select[ph-form-field]');\n formFields.forEach(field => {\n field.addEventListener('input', handleFormFieldChange);\n field.addEventListener('change', handleFormFieldChange);\n });\n\n // Initialize form data structure\n initializeFormData();\n}\n\nfunction initializeFormData(): void {\n const journey = getUserJourney();\n if (!journey) return;\n\n // Find all form containers\n const formContainers = document.querySelectorAll('[ph-form-name]');\n\n formContainers.forEach(container => {\n const formName = container.getAttribute('ph-form-name');\n if (!formName) return;\n\n // Check if this form already exists in formDetails\n const existingForm = journey.formDetails.find(form => form.formName === formName);\n\n if (!existingForm) {\n // Create new form entry\n const formFields = container.querySelectorAll('[ph-form-field]');\n const formData: FormData = {};\n\n formFields.forEach(field => {\n const fieldName = field.getAttribute('ph-form-field');\n if (fieldName) {\n formData[fieldName] = '';\n }\n });\n\n journey.formDetails.push({\n formName,\n formData\n });\n }\n });\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n}\n\nfunction handleFormFieldChange(event: Event): void {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n const fieldName = target.getAttribute('ph-form-field');\n\n if (!fieldName) return;\n\n // Find the form container\n const formContainer = target.closest('[ph-form-name]');\n if (!formContainer) return;\n\n const formName = formContainer.getAttribute('ph-form-name');\n if (!formName) return;\n\n // Update form data\n updateFormData(formName, fieldName, target.value);\n}\n\nfunction updateFormData(formName: string, fieldName: string, value: string): boolean {\n try {\n const journey = getUserJourney();\n if (!journey) return false;\n\n // Find the form in formDetails\n let formDetails = journey.formDetails.find(form => form.formName === formName);\n\n if (!formDetails) {\n // Create new form if it doesn't exist\n formDetails = {\n formName,\n formData: {}\n };\n journey.formDetails.push(formDetails);\n }\n\n // Update the field value\n formDetails.formData[fieldName] = value;\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n\n return true;\n } catch (error) {\n console.error('Error updating form data:', error);\n return false;\n }\n}\n\n// Helper function to get current journey data\nfunction getUserJourney(): UserJourney | null {\n try {\n const storedData: string | null = sessionStorage.getItem('userJourney');\n return storedData ? JSON.parse(storedData) as UserJourney : null;\n } catch (error: unknown) {\n console.error('Error getting user journey:', error);\n return null;\n }\n}\n\n// Helper function to clear journey data\nfunction clearUserJourney(): void {\n sessionStorage.removeItem('userJourney');\n}\n\n// Helper function to update page categories manually\nfunction updatePageCategories(categories: string[]): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.category = categories.length > 0 ? categories : ['Not applicable'];\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page categories:', error);\n return false;\n }\n}\n\nfunction updatePageType(type: string): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.type = type;\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page type:', error);\n return false;\n }\n}\n\n// Helper function to get journey statistics\nfunction getJourneyStats(): JourneyStats | null {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return null;\n\n const firstVisit: TouchPoint = journey.userJourney[0];\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n\n const sessionDuration: number = new Date(lastVisit.time).getTime() - new Date(firstVisit.time).getTime();\n\n return {\n totalPages: journey.userJourney.length,\n sessionDuration: Math.floor(sessionDuration / 1000), // in seconds\n firstPage: firstVisit.page,\n lastPage: lastVisit.page\n };\n}\n\n// Helper function to get specific form data\nfunction getFormData(formName: string): FormData | null {\n const journey = getUserJourney();\n if (!journey) return null;\n\n const formDetails = journey.formDetails.find(form => form.formName === formName);\n return formDetails ? formDetails.formData : null;\n}\n\n// Helper function to get all form data\nfunction getAllFormData(): FormDetails[] {\n const journey = getUserJourney();\n return journey ? journey.formDetails : [];\n}\n\n// Helper function to manually update form data\nfunction setFormData(formName: string, fieldName: string, value: string): boolean {\n return updateFormData(formName, fieldName, value);\n}\n\n// Helper function to reinitialize form tracking (useful for dynamic content)\nfunction reinitializeFormTracking(): void {\n initializeFormTracking();\n}\n\n// Auto-execute on page load\ndocument.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n});\n\n// Also execute immediately if DOM is already loaded\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n });\n} else {\n trackUserJourney();\n}\n\n// Make functions globally accessible\ndeclare global {\n interface Window {\n trackUserJourney: () => Promise<UserJourney | null>;\n getUserJourney: () => UserJourney | null;\n clearUserJourney: () => void;\n updatePageType: (type: string) => boolean;\n updatePageCategories: (categories: string[]) => boolean;\n getJourneyStats: () => JourneyStats | null;\n getFormData: (formName: string) => FormData | null;\n getAllFormData: () => FormDetails[];\n setFormData: (formName: string, fieldName: string, value: string) => boolean;\n reinitializeFormTracking: () => void;\n }\n}\n\n// Attach functions to window object for global access\nwindow.trackUserJourney = trackUserJourney;\nwindow.getUserJourney = getUserJourney;\nwindow.clearUserJourney = clearUserJourney;\nwindow.updatePageType = updatePageType;\nwindow.updatePageCategories = updatePageCategories;\nwindow.getJourneyStats = getJourneyStats;\nwindow.getFormData = getFormData;\nwindow.getAllFormData = getAllFormData;\nwindow.setFormData = setFormData;\nwindow.reinitializeFormTracking = reinitializeFormTracking;\n\n// Export functions for module usage (optional)\nexport {\n trackUserJourney,\n getUserJourney,\n clearUserJourney,\n updatePageType,\n updatePageCategories,\n getJourneyStats,\n getFormData,\n getAllFormData,\n setFormData,\n reinitializeFormTracking\n};"],
|
|
5
|
-
"mappings": ";;;AACA,MACE,OAAO,SAAS,aAAa,eAC7B,OAAO,SAAS,aAAa,aAC7B;AACA,QAAI,YAAY,GAAG,uBAAY,UAAU,EAAE;AAAA,MAAiB;AAAA,MAAU,MACpE,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,gDAAgD;AAAA,EAC9D;;;
|
|
4
|
+
"sourcesContent": ["// Only enable live reload when running on localhost\nif (\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\"\n) {\n new EventSource(`${SERVE_ORIGIN}/esbuild`).addEventListener(\"change\", () =>\n location.reload()\n );\n} else {\n console.log(\"Live reload disabled: not running on localhost\");\n}\n", "// userJourney.ts - Main tracking functionality with form details\nimport {\n UTMParameters,\n TouchPoint,\n UserJourney,\n DeviceCategory,\n UTMVisibility,\n JourneyStats,\n FormDetails\n} from '../utils/types/user-journey';\n\nexport { };\n\nasync function trackUserJourney(): Promise<UserJourney | null> {\n const STORAGE_KEY: string = 'userJourney';\n const SESSION_TIMEOUT: number = 30 * 60 * 1000; // 30 minutes\n\n // Helper function to get device category\n function getDeviceCategory(): DeviceCategory {\n const userAgent: string = navigator.userAgent;\n if (/tablet|ipad|playbook|silk/i.test(userAgent)) return 'tablet';\n if (/mobile|iphone|ipod|android|blackberry|opera|mini|windows\\sce|palm|smartphone|iemobile/i.test(userAgent)) return 'mobile';\n return 'desktop';\n }\n\n // Helper function to get browser\n function getBrowser(): string {\n const userAgent: string = navigator.userAgent;\n if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) return 'Chrome';\n if (userAgent.includes('Firefox')) return 'Firefox';\n if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) return 'Safari';\n if (userAgent.includes('Edg')) return 'Edge';\n if (userAgent.includes('Opera')) return 'Opera';\n return 'Unknown';\n }\n\n // Helper function to extract domain from referrer\n function extractDomainFromReferrer(referrer: string): string {\n if (!referrer) return 'Unknown';\n\n try {\n const url = new URL(referrer);\n const hostname = url.hostname;\n\n // Remove www. prefix if present\n const domain = hostname.replace(/^www\\./, '');\n\n // Extract the main domain name (remove TLD)\n const domainParts = domain.split('.');\n if (domainParts.length >= 2) {\n return domainParts[0];\n }\n\n return domain || 'Unknown';\n } catch (error) {\n return 'Unknown';\n }\n }\n\n // Helper function to get UTM parameters\n function getUTMParameters(isFirstVisit: boolean, firstVisitUTM?: UTMParameters): UTMParameters {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n const hasCurrentUTM: boolean = urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n\n if (isFirstVisit || hasCurrentUTM) {\n // If UTM parameters are present in URL, use them\n if (hasCurrentUTM) {\n return {\n source: urlParams.get('utm_source') || '',\n medium: urlParams.get('utm_medium') || '',\n campaign: urlParams.get('utm_campaign') || ''\n };\n } else {\n // No UTM parameters in URL, use referrer-based defaults\n const referrerDomain = extractDomainFromReferrer(document.referrer);\n return {\n source: referrerDomain,\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n } else {\n // Inherit from first visit\n return firstVisitUTM || {\n source: 'Unknown',\n medium: 'organic',\n campaign: 'unknown'\n };\n }\n }\n\n // Helper function to get page categories from global variable\n function getPageCategories(): string[] {\n try {\n // Check if global pageCategories variable exists and is an array\n if (typeof (window as any).pageCategories !== 'undefined' &&\n Array.isArray((window as any).pageCategories) &&\n (window as any).pageCategories.length > 0) {\n return (window as any).pageCategories;\n }\n\n // Return default if not available or empty\n return ['Not applicable'];\n } catch (error) {\n console.warn('Error accessing pageCategories:', error);\n return ['Not applicable'];\n }\n }\n\n function hasVisibleUTM(): boolean {\n const urlParams: URLSearchParams = new URLSearchParams(window.location.search);\n return urlParams.has('utm_source') || urlParams.has('utm_medium') || urlParams.has('utm_campaign');\n }\n\n // Helper function to get page type (customize as needed)\n function getPageType(url: string): string {\n const path: string = url.split('?')[0].toLowerCase();\n\n // Type configuration - easy to maintain and extend\n const typeConfig = {\n // Exact path matches (highest priority)\n exactMatches: {\n '/': 'Home',\n '/home': 'Home',\n '/blog': 'Blog listing',\n '/about-us': 'About us',\n '/contact-us': 'Contact',\n '/privacy-policy': 'Privacy policy',\n '/terms-of-service': 'Terms of service',\n '/careers': 'Careers',\n '/customer-stories': 'Customer stories listing',\n '/events': 'Events listing',\n '/infographics': 'Infographics listing',\n '/newsroom': 'Newsroom',\n '/releases': 'Releases listing',\n } as Record<string, string>,\n\n // Path pattern matches\n // These will match if the path starts with the pattern\n pathStartsWith: [\n { pattern: '/blog/', type: 'Blog' },\n { pattern: '/customer-stories/', type: 'Customer story' },\n { pattern: '/case-studies/', type: 'Case study' },\n { pattern: '/solutions/', type: 'Solution' },\n { pattern: '/events/', type: 'Event' },\n { pattern: '/news/', type: 'News' },\n { pattern: '/press-releases/', type: 'Press release' },\n { pattern: '/releases/', type: 'Release' },\n ]\n };\n\n // 1. Check exact matches first\n if (typeConfig.exactMatches[path]) {\n return typeConfig.exactMatches[path];\n }\n\n // 2. Check path starts with patterns\n for (const item of typeConfig.pathStartsWith) {\n if (path.startsWith(item.pattern)) {\n return item.type;\n }\n }\n\n // 3. Default fallback\n return 'Other';\n }\n\n // Check if session is still valid\n function isValidSession(journey: UserJourney): boolean {\n if (!journey.userJourney || journey.userJourney.length === 0) return false;\n\n const lastVisit: Date = new Date(journey.userJourney[journey.userJourney.length - 1].time);\n const now: Date = new Date();\n\n return (now.getTime() - lastVisit.getTime()) < SESSION_TIMEOUT;\n }\n\n // Add 200ms delay before executing the main logic\n return new Promise((resolve) => {\n setTimeout(() => {\n try {\n // Get existing journey from sessionStorage\n let journey: UserJourney | null = null;\n const storedData: string | null = sessionStorage.getItem(STORAGE_KEY);\n\n if (storedData) {\n const parsedData: UserJourney = JSON.parse(storedData);\n\n // Check if session is still valid\n if (isValidSession(parsedData)) {\n journey = parsedData;\n }\n }\n\n // Initialize new journey if none exists or session expired\n if (!journey) {\n journey = {\n userJourney: [],\n origin: window.location.hostname,\n deviceCategory: getDeviceCategory(),\n browser: getBrowser(),\n formDetails: {\n formId: '',\n formName: '',\n firstName: '',\n lastName: '',\n email: '',\n phone: ''\n }\n };\n }\n\n // Ensure formDetails exists for backward compatibility\n if (!journey.formDetails) {\n journey.formDetails = {\n formId: '',\n formName: '',\n firstName: '',\n lastName: '',\n email: '',\n phone: ''\n };\n }\n\n // Get current page info\n const currentUrl: string = window.location.pathname;\n const currentTime: string = new Date().toISOString();\n\n // Check if this is the same page as the last visit (avoid duplicates)\n const lastVisit: TouchPoint | undefined = journey.userJourney[journey.userJourney.length - 1];\n if (lastVisit && lastVisit.page === currentUrl) {\n // Same page, just update the time\n lastVisit.time = currentTime;\n } else {\n // New page visit\n const isFirstVisit: boolean = journey.userJourney.length === 0;\n const firstVisitUTM: UTMParameters | undefined = isFirstVisit ? undefined : journey.userJourney[0].utm;\n\n const touchPoint: TouchPoint = {\n touchPoint: journey.userJourney.length + 1,\n page: currentUrl,\n title: document.title || 'Untitled',\n type: getPageType(currentUrl),\n category: getPageCategories(),\n time: currentTime,\n utmVisibility: hasVisibleUTM() ? 'visible' : 'hidden',\n utm: getUTMParameters(isFirstVisit, firstVisitUTM)\n };\n\n journey.userJourney.push(touchPoint);\n }\n\n // Save updated journey to sessionStorage\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify(journey));\n\n // Initialize form tracking\n initializeFormTracking();\n\n // // Optional: Log for debugging\n // console.log('User journey updated:', journey);\n\n resolve(journey);\n\n } catch (error: unknown) {\n console.error('Error tracking user journey:', error);\n resolve(null);\n }\n }, 200); // 200ms delay\n });\n}\n\n// Form tracking functionality\nfunction initializeFormTracking(): void {\n // Remove existing event listeners to prevent duplicates\n const existingInputs = document.querySelectorAll('input[ph-form-field], textarea[ph-form-field], select[ph-form-field]');\n existingInputs.forEach(input => {\n input.removeEventListener('input', handleFormFieldChange);\n input.removeEventListener('change', handleFormFieldChange);\n });\n\n // Add event listeners to form fields\n const formFields = document.querySelectorAll('input[ph-form-field], textarea[ph-form-field], select[ph-form-field]');\n formFields.forEach(field => {\n field.addEventListener('input', handleFormFieldChange);\n field.addEventListener('change', handleFormFieldChange);\n });\n\n // Initialize form data structure\n initializeFormData();\n}\n\nfunction initializeFormData(): void {\n const journey = getUserJourney();\n if (!journey) return;\n\n // Find the form container\n const formContainer = document.querySelector('[ph-form-name]');\n if (!formContainer) return;\n\n const formName = formContainer.getAttribute('ph-form-name');\n const formId = formContainer.getAttribute('ph-form-id') || 'form-1'; // Default form ID\n\n if (!formName) return;\n\n // Initialize form details if not already set\n if (!journey.formDetails.formName) {\n journey.formDetails.formId = formId;\n journey.formDetails.formName = formName;\n }\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n}\n\nfunction handleFormFieldChange(event: Event): void {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n const fieldName = target.getAttribute('ph-form-field');\n\n if (!fieldName) return;\n\n // Find the form container\n const formContainer = target.closest('[ph-form-name]');\n if (!formContainer) return;\n\n const formName = formContainer.getAttribute('ph-form-name');\n const formId = formContainer.getAttribute('ph-form-id') || 'form-1';\n\n if (!formName) return;\n\n // Update form data\n updateFormData(formName, formId, fieldName, target.value);\n}\n\nfunction updateFormData(formName: string, formId: string, fieldName: string, value: string): boolean {\n try {\n const journey = getUserJourney();\n if (!journey) return false;\n\n // Update form details\n journey.formDetails.formId = formId;\n journey.formDetails.formName = formName;\n\n // Update the specific field\n switch (fieldName) {\n case 'firstName':\n journey.formDetails.firstName = value;\n break;\n case 'lastName':\n journey.formDetails.lastName = value;\n break;\n case 'email':\n journey.formDetails.email = value;\n break;\n case 'phone':\n journey.formDetails.phone = value;\n break;\n default:\n console.warn(`Unknown field: ${fieldName}`);\n return false;\n }\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n\n return true;\n } catch (error) {\n console.error('Error updating form data:', error);\n return false;\n }\n}\n\n// Helper function to get current journey data\nfunction getUserJourney(): UserJourney | null {\n try {\n const storedData: string | null = sessionStorage.getItem('userJourney');\n return storedData ? JSON.parse(storedData) as UserJourney : null;\n } catch (error: unknown) {\n console.error('Error getting user journey:', error);\n return null;\n }\n}\n\n// Helper function to clear journey data\nfunction clearUserJourney(): void {\n sessionStorage.removeItem('userJourney');\n}\n\n// Helper function to update page categories manually\nfunction updatePageCategories(categories: string[]): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.category = categories.length > 0 ? categories : ['Not applicable'];\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page categories:', error);\n return false;\n }\n}\n\nfunction updatePageType(type: string): boolean {\n try {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return false;\n\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n lastVisit.type = type;\n\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error: unknown) {\n console.error('Error updating page type:', error);\n return false;\n }\n}\n\n// Helper function to get journey statistics\nfunction getJourneyStats(): JourneyStats | null {\n const journey: UserJourney | null = getUserJourney();\n if (!journey || journey.userJourney.length === 0) return null;\n\n const firstVisit: TouchPoint = journey.userJourney[0];\n const lastVisit: TouchPoint = journey.userJourney[journey.userJourney.length - 1];\n\n const sessionDuration: number = new Date(lastVisit.time).getTime() - new Date(firstVisit.time).getTime();\n\n return {\n totalPages: journey.userJourney.length,\n sessionDuration: Math.floor(sessionDuration / 1000),\n firstPage: firstVisit.page,\n lastPage: lastVisit.page\n };\n}\n\n// Helper function to get form data\nfunction getFormData(): FormDetails | null {\n const journey = getUserJourney();\n return journey ? journey.formDetails : null;\n}\n\n// Helper function to get specific form field value\nfunction getFormFieldValue(fieldName: keyof FormDetails): string | null {\n const journey = getUserJourney();\n if (!journey) return null;\n\n return journey.formDetails[fieldName] || null;\n}\n\n// Helper function to manually update form data\nfunction setFormData(fieldName: keyof FormDetails, value: string): boolean {\n try {\n const journey = getUserJourney();\n if (!journey) return false;\n\n journey.formDetails[fieldName] = value;\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error) {\n console.error('Error setting form data:', error);\n return false;\n }\n}\n\n// Helper function to set form ID and name\nfunction setFormDetails(formId: string, formName: string): boolean {\n try {\n const journey = getUserJourney();\n if (!journey) return false;\n\n journey.formDetails.formId = formId;\n journey.formDetails.formName = formName;\n\n // Save updated journey\n sessionStorage.setItem('userJourney', JSON.stringify(journey));\n return true;\n } catch (error) {\n console.error('Error setting form details:', error);\n return false;\n }\n}\n\n// Helper function to reinitialize form tracking (useful for dynamic content)\nfunction reinitializeFormTracking(): void {\n initializeFormTracking();\n}\n\n// Auto-execute on page load\ndocument.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n});\n\n// Also execute immediately if DOM is already loaded\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', (): void => {\n trackUserJourney();\n });\n} else {\n trackUserJourney();\n}\n\n// Make functions globally accessible\ndeclare global {\n interface Window {\n trackUserJourney: () => Promise<UserJourney | null>;\n getUserJourney: () => UserJourney | null;\n clearUserJourney: () => void;\n updatePageType: (type: string) => boolean;\n updatePageCategories: (categories: string[]) => boolean;\n getJourneyStats: () => JourneyStats | null;\n getFormData: () => FormDetails | null;\n getFormFieldValue: (fieldName: keyof FormDetails) => string | null;\n setFormData: (fieldName: keyof FormDetails, value: string) => boolean;\n setFormDetails: (formId: string, formName: string) => boolean;\n reinitializeFormTracking: () => void;\n }\n}\n\n// Attach functions to window object for global access\nwindow.trackUserJourney = trackUserJourney;\nwindow.getUserJourney = getUserJourney;\nwindow.clearUserJourney = clearUserJourney;\nwindow.updatePageType = updatePageType;\nwindow.updatePageCategories = updatePageCategories;\nwindow.getJourneyStats = getJourneyStats;\nwindow.getFormData = getFormData;\nwindow.getFormFieldValue = getFormFieldValue;\nwindow.setFormData = setFormData;\nwindow.setFormDetails = setFormDetails;\nwindow.reinitializeFormTracking = reinitializeFormTracking;\n\n// Export functions for module usage\nexport {\n trackUserJourney,\n getUserJourney,\n clearUserJourney,\n updatePageType,\n updatePageCategories,\n getJourneyStats,\n getFormData,\n getFormFieldValue,\n setFormData,\n setFormDetails,\n reinitializeFormTracking\n};"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED