@zoyth/simple-site-framework 1.0.0

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.
Files changed (166) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +572 -0
  3. package/bin/create-simple-site.js +390 -0
  4. package/bin/simple-site.js +664 -0
  5. package/dist/client.js +135 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/client.mjs +107 -0
  8. package/dist/client.mjs.map +1 -0
  9. package/dist/components/index.d.mts +3936 -0
  10. package/dist/components/index.d.ts +3936 -0
  11. package/dist/components/index.js +38265 -0
  12. package/dist/components/index.js.map +1 -0
  13. package/dist/components/index.mjs +38173 -0
  14. package/dist/components/index.mjs.map +1 -0
  15. package/dist/config/index.d.mts +298 -0
  16. package/dist/config/index.d.ts +298 -0
  17. package/dist/config/index.js +19 -0
  18. package/dist/config/index.js.map +1 -0
  19. package/dist/config/index.mjs +1 -0
  20. package/dist/config/index.mjs.map +1 -0
  21. package/dist/index.d.mts +2184 -0
  22. package/dist/index.d.ts +2184 -0
  23. package/dist/index.js +1713 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/index.mjs +1605 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/lib/i18n/index.js +665 -0
  28. package/dist/lib/i18n/index.js.map +1 -0
  29. package/dist/lib/i18n/index.mjs +621 -0
  30. package/dist/lib/i18n/index.mjs.map +1 -0
  31. package/docs/DOCUMENTATION-STRUCTURE.md +1156 -0
  32. package/docs/EXPORTS.md +125 -0
  33. package/docs/PERFORMANCE.md +757 -0
  34. package/docs/POLICY-PAGES.md +867 -0
  35. package/docs/ROADMAP.md +334 -0
  36. package/docs/SEO.md +455 -0
  37. package/docs/SITEMAP.md +708 -0
  38. package/docs/STRUCTURED-DATA.md +671 -0
  39. package/docs/accessibility/common-patterns.md +529 -0
  40. package/docs/accessibility/keyboard-navigation.md +263 -0
  41. package/docs/accessibility/overview.md +122 -0
  42. package/docs/accessibility/screen-readers.md +311 -0
  43. package/docs/accessibility/wcag-compliance.md +159 -0
  44. package/docs/api/README.md +164 -0
  45. package/docs/api/components/Accessibility.md +356 -0
  46. package/docs/api/components/Button.md +240 -0
  47. package/docs/api/components/HeroSection.md +306 -0
  48. package/docs/architecture/decisions.md +449 -0
  49. package/docs/components/AnalyticsTracker.md +58 -0
  50. package/docs/components/AnimatedCounter.md +48 -0
  51. package/docs/components/AnimatedSection.md +56 -0
  52. package/docs/components/BlogCard.md +42 -0
  53. package/docs/components/Checkbox.md +56 -0
  54. package/docs/components/CodeBlock.md +52 -0
  55. package/docs/components/ComparisonTable.md +40 -0
  56. package/docs/components/ComponentDemo.md +38 -0
  57. package/docs/components/CountdownTimer.md +51 -0
  58. package/docs/components/ExitIntentModal.md +56 -0
  59. package/docs/components/FAQAccordion.md +66 -0
  60. package/docs/components/FeaturesGrid.md +55 -0
  61. package/docs/components/FileUpload.md +54 -0
  62. package/docs/components/I18nMetaTags.md +55 -0
  63. package/docs/components/Icon.md +53 -0
  64. package/docs/components/LazySection.md +46 -0
  65. package/docs/components/LiveProof.md +53 -0
  66. package/docs/components/LoadingSpinner.md +46 -0
  67. package/docs/components/MultiStepForm.md +48 -0
  68. package/docs/components/PolicyLayout.md +55 -0
  69. package/docs/components/PricingTable.md +49 -0
  70. package/docs/components/Radio.md +59 -0
  71. package/docs/components/SEOMetaTags.md +58 -0
  72. package/docs/components/ScriptInjector.md +50 -0
  73. package/docs/components/Select.md +72 -0
  74. package/docs/components/Skeleton.md +47 -0
  75. package/docs/components/StatsSection.md +48 -0
  76. package/docs/components/StickyBar.md +62 -0
  77. package/docs/components/StructuredData.md +99 -0
  78. package/docs/components/StyleGuide.md +46 -0
  79. package/docs/components/TableOfContents.md +47 -0
  80. package/docs/components/TestimonialCarousel.md +42 -0
  81. package/docs/components/Timeline.md +51 -0
  82. package/docs/components/Toast.md +59 -0
  83. package/docs/components/TrackedLink.md +62 -0
  84. package/docs/components/TrustBadges.md +44 -0
  85. package/docs/components/conversion/MobileCTA.md +363 -0
  86. package/docs/components/forms/ContactForm.md +75 -0
  87. package/docs/components/forms/FormField.md +74 -0
  88. package/docs/components/layout/Footer.md +601 -0
  89. package/docs/components/layout/Header.md +549 -0
  90. package/docs/components/layout/LanguageSelector.md +54 -0
  91. package/docs/components/layout/LanguageSwitcher.md +24 -0
  92. package/docs/components/overview.md +447 -0
  93. package/docs/components/sections/AboutSection.md +48 -0
  94. package/docs/components/sections/CTASection.md +596 -0
  95. package/docs/components/sections/CaseStudySection.md +47 -0
  96. package/docs/components/sections/ContactSection.md +599 -0
  97. package/docs/components/sections/FeatureSection.md +44 -0
  98. package/docs/components/sections/HeroSection.md +404 -0
  99. package/docs/components/sections/LogosSection.md +47 -0
  100. package/docs/components/sections/PersonalTaxesSection.md +23 -0
  101. package/docs/components/sections/RecruitingSection.md +23 -0
  102. package/docs/components/sections/SecurePortalSection.md +23 -0
  103. package/docs/components/sections/ServicePageLayout.md +52 -0
  104. package/docs/components/sections/ServicesSection.md +49 -0
  105. package/docs/components/sections/TestimonialSection.md +44 -0
  106. package/docs/components/sections/WhyChooseUsSection.md +54 -0
  107. package/docs/components/ui/Breadcrumb.md +70 -0
  108. package/docs/components/ui/Button.md +514 -0
  109. package/docs/components/ui/Card.md +501 -0
  110. package/docs/components/ui/Input.md +54 -0
  111. package/docs/components/ui/MobileLinks.md +43 -0
  112. package/docs/components/ui/Modal.md +60 -0
  113. package/docs/components/ui/Tabs.md +62 -0
  114. package/docs/components/ui/Textarea.md +52 -0
  115. package/docs/core-concepts/configuration-driven.md +552 -0
  116. package/docs/core-concepts/overview.md +351 -0
  117. package/docs/features/accessibility/README.md +73 -0
  118. package/docs/features/accessibility/aria-support.md +177 -0
  119. package/docs/features/accessibility/color-contrast.md +155 -0
  120. package/docs/features/accessibility/focus-management.md +187 -0
  121. package/docs/features/accessibility/testing.md +196 -0
  122. package/docs/features/analytics/README.md +51 -0
  123. package/docs/features/analytics/ab-testing.md +171 -0
  124. package/docs/features/analytics/conversion-tracking.md +207 -0
  125. package/docs/features/analytics/custom-events.md +219 -0
  126. package/docs/features/analytics/privacy.md +198 -0
  127. package/docs/features/analytics/setup.md +114 -0
  128. package/docs/features/analytics/tracking-events.md +224 -0
  129. package/docs/features/i18n/README.md +51 -0
  130. package/docs/features/i18n/best-practices.md +273 -0
  131. package/docs/features/i18n/configuration.md +84 -0
  132. package/docs/features/i18n/formatting.md +133 -0
  133. package/docs/features/i18n/locale-detection.md +122 -0
  134. package/docs/features/i18n/routing.md +99 -0
  135. package/docs/features/i18n/rtl-support.md +191 -0
  136. package/docs/features/i18n/translations.md +129 -0
  137. package/docs/features/internationalization.md +595 -0
  138. package/docs/features/performance/README.md +77 -0
  139. package/docs/features/performance/bundle-size.md +134 -0
  140. package/docs/features/performance/caching.md +131 -0
  141. package/docs/features/performance/code-splitting.md +121 -0
  142. package/docs/features/performance/image-optimization.md +110 -0
  143. package/docs/features/performance/lazy-loading.md +92 -0
  144. package/docs/features/performance/monitoring.md +148 -0
  145. package/docs/features/seo/README.md +51 -0
  146. package/docs/features/seo/best-practices.md +184 -0
  147. package/docs/features/seo/canonical-urls.md +182 -0
  148. package/docs/features/seo/meta-tags.md +126 -0
  149. package/docs/features/seo/open-graph.md +166 -0
  150. package/docs/features/seo/robots-txt.md +146 -0
  151. package/docs/features/seo/sitemaps.md +162 -0
  152. package/docs/features/seo/structured-data.md +166 -0
  153. package/docs/getting-started/installation.md +292 -0
  154. package/docs/getting-started/introduction.md +195 -0
  155. package/docs/getting-started/quick-start.md +460 -0
  156. package/docs/guides/analytics-setup.md +616 -0
  157. package/docs/i18n/CONFIGURATION.md +353 -0
  158. package/docs/i18n/EXAMPLES.md +402 -0
  159. package/docs/i18n/MIGRATION.md +260 -0
  160. package/docs/i18n/SEO.md +392 -0
  161. package/docs/i18n/STATIC-GENERATION-FIX.md +71 -0
  162. package/docs/migration/changelog.md +136 -0
  163. package/docs/migration/overview.md +233 -0
  164. package/docs/recipes/adding-animations.md +475 -0
  165. package/docs/recipes/forms-with-validation.md +393 -0
  166. package/package.json +152 -0
@@ -0,0 +1,171 @@
1
+ # A/B Testing
2
+
3
+ Run experiments to optimize conversions and user engagement.
4
+
5
+ ## Overview
6
+
7
+ The framework provides a client-side A/B testing system that:
8
+
9
+ - Assigns users to variants deterministically
10
+ - Persists assignments across sessions
11
+ - Integrates with analytics tracking
12
+ - Supports weighted variant distribution
13
+
14
+ ## Quick Start
15
+
16
+ ```typescript
17
+ 'use client';
18
+ import { getABTestVariant, trackABTestEvent } from '@zoyth/simple-site-framework/client';
19
+
20
+ const variant = getABTestVariant({
21
+ testId: 'hero-cta',
22
+ variants: { A: { weight: 50 }, B: { weight: 50 } },
23
+ });
24
+
25
+ const ctaText = variant === 'A' ? 'Start Free Trial' : 'Get Started Free';
26
+
27
+ <button onClick={() => trackABTestEvent('hero-cta', variant, 'click')}>
28
+ {ctaText}
29
+ </button>
30
+ ```
31
+
32
+ ## Setting Up a Test
33
+
34
+ ### 1. Define the Test
35
+
36
+ ```typescript
37
+ const test = {
38
+ testId: 'pricing-layout',
39
+ variants: {
40
+ control: { weight: 50 },
41
+ cards: { weight: 50 },
42
+ },
43
+ };
44
+ ```
45
+
46
+ ### 2. Get Variant Assignment
47
+
48
+ ```typescript
49
+ const variant = getABTestVariant(test);
50
+ // Returns 'control' or 'cards'
51
+ ```
52
+
53
+ ### 3. Render Based on Variant
54
+
55
+ ```typescript
56
+ {variant === 'control' ? (
57
+ <PricingTable layout="table" />
58
+ ) : (
59
+ <PricingTable layout="cards" />
60
+ )}
61
+ ```
62
+
63
+ ### 4. Track Conversions
64
+
65
+ ```typescript
66
+ function handlePurchase() {
67
+ trackABTestEvent('pricing-layout', variant, 'purchase');
68
+ }
69
+ ```
70
+
71
+ ## Variant Assignment
72
+
73
+ ### How It Works
74
+
75
+ 1. User visits page with A/B test
76
+ 2. Framework generates or retrieves user ID
77
+ 3. User ID + test ID produces deterministic hash
78
+ 4. Hash maps to variant based on weights
79
+ 5. Assignment persists via cookie/localStorage
80
+
81
+ ### Weighted Distribution
82
+
83
+ ```typescript
84
+ // Equal split
85
+ variants: { A: { weight: 50 }, B: { weight: 50 } }
86
+
87
+ // 80/20 split
88
+ variants: { control: { weight: 80 }, experiment: { weight: 20 } }
89
+
90
+ // Three-way split
91
+ variants: { A: { weight: 33 }, B: { weight: 33 }, C: { weight: 34 } }
92
+ ```
93
+
94
+ Weights don't need to sum to 100 - they're relative proportions.
95
+
96
+ ## Tracking Test Events
97
+
98
+ ### trackABTestEvent
99
+
100
+ ```typescript
101
+ import { trackABTestEvent } from '@zoyth/simple-site-framework/client';
102
+
103
+ // Track exposure (user saw the variant)
104
+ trackABTestEvent('test-id', variant, 'exposure');
105
+
106
+ // Track interaction
107
+ trackABTestEvent('test-id', variant, 'click');
108
+
109
+ // Track conversion
110
+ trackABTestEvent('test-id', variant, 'conversion');
111
+ ```
112
+
113
+ ### Custom Event Data
114
+
115
+ ```typescript
116
+ trackABTestEvent('test-id', variant, 'purchase', {
117
+ value: 49.99,
118
+ currency: 'USD',
119
+ });
120
+ ```
121
+
122
+ ## Multi-Page Tests
123
+
124
+ For tests spanning multiple pages, variant persists automatically:
125
+
126
+ ```typescript
127
+ // Page 1: Assign variant
128
+ const variant = getABTestVariant({
129
+ testId: 'onboarding-flow',
130
+ variants: { A: { weight: 50 }, B: { weight: 50 } },
131
+ });
132
+
133
+ // Page 2: Same variant returned
134
+ const variant = getABTestVariant({
135
+ testId: 'onboarding-flow',
136
+ variants: { A: { weight: 50 }, B: { weight: 50 } },
137
+ });
138
+ // Same user always gets the same variant
139
+ ```
140
+
141
+ ## Analyzing Results
142
+
143
+ ### In Google Analytics 4
144
+
145
+ 1. Navigate to Explore > Free Form
146
+ 2. Add dimension: Custom Event Parameter > `ab_test_id`
147
+ 3. Add dimension: Custom Event Parameter > `ab_variant`
148
+ 4. Add metric: Event count, Conversions
149
+ 5. Compare variant performance
150
+
151
+ ### Statistical Significance
152
+
153
+ - Run tests for at least 2 weeks
154
+ - Aim for 1,000+ visitors per variant
155
+ - Use a significance calculator before concluding
156
+ - Don't stop tests early on promising results
157
+
158
+ ## Best Practices
159
+
160
+ - Test one variable at a time
161
+ - Define success metrics before starting
162
+ - Run tests long enough for statistical significance
163
+ - Document all active tests
164
+ - Clean up completed tests
165
+ - Don't nest A/B tests unless variants are independent
166
+
167
+ ## See Also
168
+
169
+ - [Tracking Events](./tracking-events.md)
170
+ - [Conversion Tracking](./conversion-tracking.md)
171
+ - [A/B Testing Guide](../../guides/ab-testing.md)
@@ -0,0 +1,207 @@
1
+ # Conversion Tracking
2
+
3
+ Track goals and measure conversion rates.
4
+
5
+ ## Overview
6
+
7
+ Conversion tracking measures when users complete desired actions:
8
+
9
+ - Form submissions
10
+ - CTA clicks
11
+ - Sign-ups
12
+ - Purchases
13
+ - Downloads
14
+ - Phone calls
15
+
16
+ ## Tracking Conversions
17
+
18
+ ### trackConversion
19
+
20
+ ```typescript
21
+ 'use client';
22
+ import { trackConversion } from '@zoyth/simple-site-framework/client';
23
+
24
+ function handleSignup() {
25
+ trackConversion('signup_complete', {
26
+ method: 'email',
27
+ source: 'hero_cta',
28
+ });
29
+ }
30
+ ```
31
+
32
+ ### trackCTAClick
33
+
34
+ Shorthand for CTA conversion tracking:
35
+
36
+ ```typescript
37
+ import { trackCTAClick } from '@zoyth/simple-site-framework/client';
38
+
39
+ <button onClick={() => trackCTAClick('get-started', 'pricing-page')}>
40
+ Get Started
41
+ </button>
42
+ ```
43
+
44
+ ## Common Conversion Types
45
+
46
+ ### Form Submission
47
+
48
+ ```typescript
49
+ function handleFormSubmit(formData) {
50
+ trackConversion('form_submit', {
51
+ form_name: 'contact',
52
+ form_location: 'contact_page',
53
+ });
54
+ }
55
+ ```
56
+
57
+ ### Lead Generation
58
+
59
+ ```typescript
60
+ trackConversion('lead_generated', {
61
+ lead_type: 'demo_request',
62
+ source: 'landing_page',
63
+ });
64
+ ```
65
+
66
+ ### Purchase
67
+
68
+ ```typescript
69
+ trackConversion('purchase', {
70
+ transaction_id: 'T12345',
71
+ value: 99.99,
72
+ currency: 'USD',
73
+ items: ['pro_plan'],
74
+ });
75
+ ```
76
+
77
+ ### Download
78
+
79
+ ```typescript
80
+ trackConversion('file_download', {
81
+ file_name: 'whitepaper.pdf',
82
+ file_type: 'pdf',
83
+ });
84
+ ```
85
+
86
+ ### Phone Call
87
+
88
+ ```typescript
89
+ <TrackedLink
90
+ href="tel:+15551234567"
91
+ eventName="phone_call"
92
+ eventData={{ location: 'header' }}
93
+ >
94
+ Call Us
95
+ </TrackedLink>
96
+ ```
97
+
98
+ ## Conversion Funnels
99
+
100
+ Track multi-step conversion paths:
101
+
102
+ ```typescript
103
+ // Step 1: View pricing
104
+ trackEvent('funnel_step', {
105
+ funnel: 'signup',
106
+ step: 1,
107
+ step_name: 'view_pricing',
108
+ });
109
+
110
+ // Step 2: Select plan
111
+ trackEvent('funnel_step', {
112
+ funnel: 'signup',
113
+ step: 2,
114
+ step_name: 'select_plan',
115
+ plan: 'pro',
116
+ });
117
+
118
+ // Step 3: Complete signup
119
+ trackConversion('signup_complete', {
120
+ funnel: 'signup',
121
+ step: 3,
122
+ plan: 'pro',
123
+ });
124
+ ```
125
+
126
+ ## GTM Conversion Setup
127
+
128
+ ### Google Ads Conversions
129
+
130
+ 1. In GTM, create Conversion Linker tag
131
+ 2. Create Google Ads Conversion Tracking tag
132
+ 3. Set trigger to fire on your conversion event
133
+ 4. Add conversion ID and label from Google Ads
134
+
135
+ ### GA4 Conversions
136
+
137
+ 1. In GA4, go to Configure > Events
138
+ 2. Find your conversion event
139
+ 3. Toggle "Mark as conversion"
140
+
141
+ ## Conversion Attribution
142
+
143
+ ### First Click
144
+
145
+ Attribute to first touchpoint:
146
+
147
+ ```typescript
148
+ trackConversion('signup', {
149
+ first_touch_source: sessionStorage.getItem('first_source'),
150
+ first_touch_medium: sessionStorage.getItem('first_medium'),
151
+ });
152
+ ```
153
+
154
+ ### Last Click
155
+
156
+ Attribute to most recent touchpoint:
157
+
158
+ ```typescript
159
+ trackConversion('signup', {
160
+ utm_source: searchParams.get('utm_source'),
161
+ utm_medium: searchParams.get('utm_medium'),
162
+ utm_campaign: searchParams.get('utm_campaign'),
163
+ });
164
+ ```
165
+
166
+ ## Conversion Components
167
+
168
+ ### MobileCTA
169
+
170
+ Sticky mobile CTA with built-in conversion tracking:
171
+
172
+ ```typescript
173
+ import { MobileCTA } from '@zoyth/simple-site-framework/components';
174
+
175
+ <MobileCTA
176
+ text="Get Started"
177
+ href="/signup"
178
+ trackingId="mobile-cta-signup"
179
+ />
180
+ ```
181
+
182
+ ### ExitIntentModal
183
+
184
+ Track exit-intent conversions:
185
+
186
+ ```typescript
187
+ import { ExitIntentModal } from '@zoyth/simple-site-framework/components';
188
+
189
+ <ExitIntentModal
190
+ onConversion={() => trackConversion('exit_intent_signup')}
191
+ />
192
+ ```
193
+
194
+ ## Best Practices
195
+
196
+ - Define conversions before building pages
197
+ - Track micro-conversions (newsletter signup) and macro-conversions (purchase)
198
+ - Include attribution data with conversions
199
+ - Test conversion tracking in staging before production
200
+ - Monitor conversion rates over time for regressions
201
+
202
+ ## See Also
203
+
204
+ - [Tracking Events](./tracking-events.md)
205
+ - [A/B Testing](./ab-testing.md)
206
+ - [MobileCTA Component](../../components/conversion/MobileCTA.md)
207
+ - [ExitIntentModal Component](../../components/ExitIntentModal.md)
@@ -0,0 +1,219 @@
1
+ # Custom Events
2
+
3
+ Define and track application-specific events.
4
+
5
+ ## Overview
6
+
7
+ Beyond built-in tracking helpers, you can define custom events tailored to your application's needs.
8
+
9
+ ## Creating Custom Events
10
+
11
+ ### Basic Custom Event
12
+
13
+ ```typescript
14
+ 'use client';
15
+ import { trackEvent } from '@zoyth/simple-site-framework/client';
16
+
17
+ trackEvent('feature_used', {
18
+ feature_name: 'dark_mode',
19
+ action: 'toggle_on',
20
+ });
21
+ ```
22
+
23
+ ### Typed Custom Events
24
+
25
+ Define types for consistency:
26
+
27
+ ```typescript
28
+ type AppEvent =
29
+ | { name: 'feature_used'; data: { feature_name: string; action: string } }
30
+ | { name: 'content_viewed'; data: { content_id: string; content_type: string } }
31
+ | { name: 'search_performed'; data: { query: string; results_count: number } };
32
+
33
+ function trackAppEvent(event: AppEvent) {
34
+ trackEvent(event.name, event.data);
35
+ }
36
+
37
+ // Usage
38
+ trackAppEvent({
39
+ name: 'search_performed',
40
+ data: { query: 'pricing', results_count: 5 },
41
+ });
42
+ ```
43
+
44
+ ## Event Naming Conventions
45
+
46
+ ### Recommended Format
47
+
48
+ Use `object_action` pattern in snake_case:
49
+
50
+ ```typescript
51
+ // ✅ Good
52
+ 'button_click'
53
+ 'form_submit'
54
+ 'video_play'
55
+ 'page_scroll'
56
+ 'menu_open'
57
+ 'search_complete'
58
+
59
+ // ❌ Bad
60
+ 'clickButton' // camelCase
61
+ 'FORM_SUBMIT' // UPPER_CASE
62
+ 'user clicked btn' // spaces
63
+ 'click' // too vague
64
+ ```
65
+
66
+ ### Category Prefixes
67
+
68
+ Group related events:
69
+
70
+ ```typescript
71
+ // Navigation
72
+ 'nav_menu_open'
73
+ 'nav_link_click'
74
+ 'nav_search_used'
75
+
76
+ // Content
77
+ 'content_viewed'
78
+ 'content_shared'
79
+ 'content_bookmarked'
80
+
81
+ // Commerce
82
+ 'product_viewed'
83
+ 'cart_updated'
84
+ 'checkout_started'
85
+ ```
86
+
87
+ ## Event Properties
88
+
89
+ ### Standard Properties
90
+
91
+ Include consistent context:
92
+
93
+ ```typescript
94
+ trackEvent('button_click', {
95
+ // What
96
+ element_id: 'hero-cta',
97
+ element_text: 'Get Started',
98
+
99
+ // Where
100
+ page_path: '/pricing',
101
+ page_section: 'hero',
102
+
103
+ // Context
104
+ locale: 'en',
105
+ viewport: 'desktop',
106
+ });
107
+ ```
108
+
109
+ ### Dynamic Properties
110
+
111
+ Capture runtime context:
112
+
113
+ ```typescript
114
+ function trackInteraction(elementId: string, action: string) {
115
+ trackEvent(`${elementId}_${action}`, {
116
+ timestamp: Date.now(),
117
+ page_path: window.location.pathname,
118
+ referrer: document.referrer,
119
+ screen_width: window.innerWidth,
120
+ });
121
+ }
122
+ ```
123
+
124
+ ## Custom Event Patterns
125
+
126
+ ### Feature Usage Tracking
127
+
128
+ ```typescript
129
+ function trackFeatureUsage(feature: string) {
130
+ trackEvent('feature_used', {
131
+ feature,
132
+ session_id: getSessionId(),
133
+ usage_count: incrementUsageCount(feature),
134
+ });
135
+ }
136
+ ```
137
+
138
+ ### Error Tracking
139
+
140
+ ```typescript
141
+ function trackError(error: Error, context: string) {
142
+ trackEvent('app_error', {
143
+ error_message: error.message,
144
+ error_type: error.name,
145
+ context,
146
+ page_path: window.location.pathname,
147
+ });
148
+ }
149
+ ```
150
+
151
+ ### User Engagement
152
+
153
+ ```typescript
154
+ function trackEngagement(type: string, duration?: number) {
155
+ trackEvent('user_engagement', {
156
+ engagement_type: type,
157
+ engagement_duration: duration,
158
+ page_path: window.location.pathname,
159
+ });
160
+ }
161
+
162
+ // Track time on page
163
+ trackEngagement('time_on_page', 45);
164
+
165
+ // Track interaction
166
+ trackEngagement('comment_posted');
167
+ ```
168
+
169
+ ### Search Tracking
170
+
171
+ ```typescript
172
+ function trackSearch(query: string, results: number) {
173
+ trackEvent('search', {
174
+ search_term: query,
175
+ results_count: results,
176
+ search_type: 'site_search',
177
+ });
178
+ }
179
+
180
+ function trackSearchClick(query: string, position: number) {
181
+ trackEvent('search_result_click', {
182
+ search_term: query,
183
+ click_position: position,
184
+ });
185
+ }
186
+ ```
187
+
188
+ ## GTM Integration
189
+
190
+ Custom events push to GTM dataLayer:
191
+
192
+ ```typescript
193
+ // Framework automatically pushes to dataLayer
194
+ trackEvent('custom_event', { key: 'value' });
195
+
196
+ // Equivalent to:
197
+ window.dataLayer.push({
198
+ event: 'custom_event',
199
+ key: 'value',
200
+ });
201
+ ```
202
+
203
+ In GTM, create triggers based on custom event names to fire tags.
204
+
205
+ ## Best Practices
206
+
207
+ - Document your event taxonomy
208
+ - Use consistent naming conventions across the team
209
+ - Include enough context to make events actionable
210
+ - Avoid tracking PII (emails, names, phone numbers)
211
+ - Don't over-track - focus on events that inform decisions
212
+ - Test events in GTM Preview mode before deploying
213
+ - Review and prune unused events periodically
214
+
215
+ ## See Also
216
+
217
+ - [Tracking Events](./tracking-events.md)
218
+ - [Conversion Tracking](./conversion-tracking.md)
219
+ - [Privacy](./privacy.md)