@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.
- package/LICENSE +21 -0
- package/README.md +572 -0
- package/bin/create-simple-site.js +390 -0
- package/bin/simple-site.js +664 -0
- package/dist/client.js +135 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +107 -0
- package/dist/client.mjs.map +1 -0
- package/dist/components/index.d.mts +3936 -0
- package/dist/components/index.d.ts +3936 -0
- package/dist/components/index.js +38265 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +38173 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/index.d.mts +298 -0
- package/dist/config/index.d.ts +298 -0
- package/dist/config/index.js +19 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +1 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/index.d.mts +2184 -0
- package/dist/index.d.ts +2184 -0
- package/dist/index.js +1713 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1605 -0
- package/dist/index.mjs.map +1 -0
- package/dist/lib/i18n/index.js +665 -0
- package/dist/lib/i18n/index.js.map +1 -0
- package/dist/lib/i18n/index.mjs +621 -0
- package/dist/lib/i18n/index.mjs.map +1 -0
- package/docs/DOCUMENTATION-STRUCTURE.md +1156 -0
- package/docs/EXPORTS.md +125 -0
- package/docs/PERFORMANCE.md +757 -0
- package/docs/POLICY-PAGES.md +867 -0
- package/docs/ROADMAP.md +334 -0
- package/docs/SEO.md +455 -0
- package/docs/SITEMAP.md +708 -0
- package/docs/STRUCTURED-DATA.md +671 -0
- package/docs/accessibility/common-patterns.md +529 -0
- package/docs/accessibility/keyboard-navigation.md +263 -0
- package/docs/accessibility/overview.md +122 -0
- package/docs/accessibility/screen-readers.md +311 -0
- package/docs/accessibility/wcag-compliance.md +159 -0
- package/docs/api/README.md +164 -0
- package/docs/api/components/Accessibility.md +356 -0
- package/docs/api/components/Button.md +240 -0
- package/docs/api/components/HeroSection.md +306 -0
- package/docs/architecture/decisions.md +449 -0
- package/docs/components/AnalyticsTracker.md +58 -0
- package/docs/components/AnimatedCounter.md +48 -0
- package/docs/components/AnimatedSection.md +56 -0
- package/docs/components/BlogCard.md +42 -0
- package/docs/components/Checkbox.md +56 -0
- package/docs/components/CodeBlock.md +52 -0
- package/docs/components/ComparisonTable.md +40 -0
- package/docs/components/ComponentDemo.md +38 -0
- package/docs/components/CountdownTimer.md +51 -0
- package/docs/components/ExitIntentModal.md +56 -0
- package/docs/components/FAQAccordion.md +66 -0
- package/docs/components/FeaturesGrid.md +55 -0
- package/docs/components/FileUpload.md +54 -0
- package/docs/components/I18nMetaTags.md +55 -0
- package/docs/components/Icon.md +53 -0
- package/docs/components/LazySection.md +46 -0
- package/docs/components/LiveProof.md +53 -0
- package/docs/components/LoadingSpinner.md +46 -0
- package/docs/components/MultiStepForm.md +48 -0
- package/docs/components/PolicyLayout.md +55 -0
- package/docs/components/PricingTable.md +49 -0
- package/docs/components/Radio.md +59 -0
- package/docs/components/SEOMetaTags.md +58 -0
- package/docs/components/ScriptInjector.md +50 -0
- package/docs/components/Select.md +72 -0
- package/docs/components/Skeleton.md +47 -0
- package/docs/components/StatsSection.md +48 -0
- package/docs/components/StickyBar.md +62 -0
- package/docs/components/StructuredData.md +99 -0
- package/docs/components/StyleGuide.md +46 -0
- package/docs/components/TableOfContents.md +47 -0
- package/docs/components/TestimonialCarousel.md +42 -0
- package/docs/components/Timeline.md +51 -0
- package/docs/components/Toast.md +59 -0
- package/docs/components/TrackedLink.md +62 -0
- package/docs/components/TrustBadges.md +44 -0
- package/docs/components/conversion/MobileCTA.md +363 -0
- package/docs/components/forms/ContactForm.md +75 -0
- package/docs/components/forms/FormField.md +74 -0
- package/docs/components/layout/Footer.md +601 -0
- package/docs/components/layout/Header.md +549 -0
- package/docs/components/layout/LanguageSelector.md +54 -0
- package/docs/components/layout/LanguageSwitcher.md +24 -0
- package/docs/components/overview.md +447 -0
- package/docs/components/sections/AboutSection.md +48 -0
- package/docs/components/sections/CTASection.md +596 -0
- package/docs/components/sections/CaseStudySection.md +47 -0
- package/docs/components/sections/ContactSection.md +599 -0
- package/docs/components/sections/FeatureSection.md +44 -0
- package/docs/components/sections/HeroSection.md +404 -0
- package/docs/components/sections/LogosSection.md +47 -0
- package/docs/components/sections/PersonalTaxesSection.md +23 -0
- package/docs/components/sections/RecruitingSection.md +23 -0
- package/docs/components/sections/SecurePortalSection.md +23 -0
- package/docs/components/sections/ServicePageLayout.md +52 -0
- package/docs/components/sections/ServicesSection.md +49 -0
- package/docs/components/sections/TestimonialSection.md +44 -0
- package/docs/components/sections/WhyChooseUsSection.md +54 -0
- package/docs/components/ui/Breadcrumb.md +70 -0
- package/docs/components/ui/Button.md +514 -0
- package/docs/components/ui/Card.md +501 -0
- package/docs/components/ui/Input.md +54 -0
- package/docs/components/ui/MobileLinks.md +43 -0
- package/docs/components/ui/Modal.md +60 -0
- package/docs/components/ui/Tabs.md +62 -0
- package/docs/components/ui/Textarea.md +52 -0
- package/docs/core-concepts/configuration-driven.md +552 -0
- package/docs/core-concepts/overview.md +351 -0
- package/docs/features/accessibility/README.md +73 -0
- package/docs/features/accessibility/aria-support.md +177 -0
- package/docs/features/accessibility/color-contrast.md +155 -0
- package/docs/features/accessibility/focus-management.md +187 -0
- package/docs/features/accessibility/testing.md +196 -0
- package/docs/features/analytics/README.md +51 -0
- package/docs/features/analytics/ab-testing.md +171 -0
- package/docs/features/analytics/conversion-tracking.md +207 -0
- package/docs/features/analytics/custom-events.md +219 -0
- package/docs/features/analytics/privacy.md +198 -0
- package/docs/features/analytics/setup.md +114 -0
- package/docs/features/analytics/tracking-events.md +224 -0
- package/docs/features/i18n/README.md +51 -0
- package/docs/features/i18n/best-practices.md +273 -0
- package/docs/features/i18n/configuration.md +84 -0
- package/docs/features/i18n/formatting.md +133 -0
- package/docs/features/i18n/locale-detection.md +122 -0
- package/docs/features/i18n/routing.md +99 -0
- package/docs/features/i18n/rtl-support.md +191 -0
- package/docs/features/i18n/translations.md +129 -0
- package/docs/features/internationalization.md +595 -0
- package/docs/features/performance/README.md +77 -0
- package/docs/features/performance/bundle-size.md +134 -0
- package/docs/features/performance/caching.md +131 -0
- package/docs/features/performance/code-splitting.md +121 -0
- package/docs/features/performance/image-optimization.md +110 -0
- package/docs/features/performance/lazy-loading.md +92 -0
- package/docs/features/performance/monitoring.md +148 -0
- package/docs/features/seo/README.md +51 -0
- package/docs/features/seo/best-practices.md +184 -0
- package/docs/features/seo/canonical-urls.md +182 -0
- package/docs/features/seo/meta-tags.md +126 -0
- package/docs/features/seo/open-graph.md +166 -0
- package/docs/features/seo/robots-txt.md +146 -0
- package/docs/features/seo/sitemaps.md +162 -0
- package/docs/features/seo/structured-data.md +166 -0
- package/docs/getting-started/installation.md +292 -0
- package/docs/getting-started/introduction.md +195 -0
- package/docs/getting-started/quick-start.md +460 -0
- package/docs/guides/analytics-setup.md +616 -0
- package/docs/i18n/CONFIGURATION.md +353 -0
- package/docs/i18n/EXAMPLES.md +402 -0
- package/docs/i18n/MIGRATION.md +260 -0
- package/docs/i18n/SEO.md +392 -0
- package/docs/i18n/STATIC-GENERATION-FIX.md +71 -0
- package/docs/migration/changelog.md +136 -0
- package/docs/migration/overview.md +233 -0
- package/docs/recipes/adding-animations.md +475 -0
- package/docs/recipes/forms-with-validation.md +393 -0
- package/package.json +152 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Analytics Privacy
|
|
2
|
+
|
|
3
|
+
GDPR compliance and privacy-respecting analytics.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The framework supports privacy-compliant analytics through:
|
|
8
|
+
|
|
9
|
+
- Consent-based tracking
|
|
10
|
+
- Cookie management
|
|
11
|
+
- Data minimization
|
|
12
|
+
- GTM consent mode
|
|
13
|
+
|
|
14
|
+
## Consent Management
|
|
15
|
+
|
|
16
|
+
### Consent Banner
|
|
17
|
+
|
|
18
|
+
Implement a consent banner before loading analytics:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
'use client';
|
|
22
|
+
import { useState, useEffect } from 'react';
|
|
23
|
+
import { AnalyticsTracker } from '@zoyth/simple-site-framework/components';
|
|
24
|
+
|
|
25
|
+
function Layout({ children }) {
|
|
26
|
+
const [consent, setConsent] = useState<boolean | null>(null);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const stored = localStorage.getItem('analytics_consent');
|
|
30
|
+
if (stored !== null) setConsent(stored === 'true');
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
{consent && <AnalyticsTracker gtmId="GTM-XXXXXXX" />}
|
|
36
|
+
{consent === null && (
|
|
37
|
+
<CookieBanner
|
|
38
|
+
onAccept={() => {
|
|
39
|
+
localStorage.setItem('analytics_consent', 'true');
|
|
40
|
+
setConsent(true);
|
|
41
|
+
}}
|
|
42
|
+
onDecline={() => {
|
|
43
|
+
localStorage.setItem('analytics_consent', 'false');
|
|
44
|
+
setConsent(false);
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
{children}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### GTM Consent Mode
|
|
55
|
+
|
|
56
|
+
Use Google's consent mode for nuanced control:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// Initialize with denied consent
|
|
60
|
+
window.dataLayer = window.dataLayer || [];
|
|
61
|
+
window.dataLayer.push({
|
|
62
|
+
'consent': 'default',
|
|
63
|
+
'analytics_storage': 'denied',
|
|
64
|
+
'ad_storage': 'denied',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Update when user consents
|
|
68
|
+
function grantConsent() {
|
|
69
|
+
window.dataLayer.push({
|
|
70
|
+
'consent': 'update',
|
|
71
|
+
'analytics_storage': 'granted',
|
|
72
|
+
'ad_storage': 'granted',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## GDPR Compliance
|
|
78
|
+
|
|
79
|
+
### Data Minimization
|
|
80
|
+
|
|
81
|
+
Only track necessary data:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// ✅ Good - Minimal data
|
|
85
|
+
trackEvent('cta_click', {
|
|
86
|
+
cta_id: 'hero-signup',
|
|
87
|
+
page: '/pricing',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ❌ Bad - Excessive data
|
|
91
|
+
trackEvent('cta_click', {
|
|
92
|
+
cta_id: 'hero-signup',
|
|
93
|
+
user_email: user.email, // PII
|
|
94
|
+
user_name: user.name, // PII
|
|
95
|
+
ip_address: user.ip, // PII
|
|
96
|
+
browser_fingerprint: hash, // Identifying
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Never Track PII
|
|
101
|
+
|
|
102
|
+
Do not include in events:
|
|
103
|
+
- Email addresses
|
|
104
|
+
- Names
|
|
105
|
+
- Phone numbers
|
|
106
|
+
- IP addresses (handled by GA4 settings)
|
|
107
|
+
- Precise location data
|
|
108
|
+
- User IDs that map to real identities
|
|
109
|
+
|
|
110
|
+
### Right to Erasure
|
|
111
|
+
|
|
112
|
+
Support data deletion requests:
|
|
113
|
+
|
|
114
|
+
1. Use GA4 User Deletion API
|
|
115
|
+
2. Delete user data from GTM server-side
|
|
116
|
+
3. Clear local cookies and storage
|
|
117
|
+
|
|
118
|
+
### Data Retention
|
|
119
|
+
|
|
120
|
+
Configure retention in GA4:
|
|
121
|
+
1. GA4 Admin > Data Settings > Data Retention
|
|
122
|
+
2. Set to shortest period needed (2 or 14 months)
|
|
123
|
+
|
|
124
|
+
## Cookie Management
|
|
125
|
+
|
|
126
|
+
### Analytics Cookies
|
|
127
|
+
|
|
128
|
+
Common analytics cookies:
|
|
129
|
+
|
|
130
|
+
| Cookie | Purpose | Duration |
|
|
131
|
+
|--------|---------|----------|
|
|
132
|
+
| `_ga` | GA4 user identification | 2 years |
|
|
133
|
+
| `_ga_*` | GA4 session | 2 years |
|
|
134
|
+
| `_gid` | GA4 session | 24 hours |
|
|
135
|
+
| `_gat` | GA4 throttle | 1 minute |
|
|
136
|
+
|
|
137
|
+
### Cookie-Free Tracking
|
|
138
|
+
|
|
139
|
+
For stricter privacy requirements:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Use sessionStorage instead of cookies
|
|
143
|
+
<AnalyticsTracker
|
|
144
|
+
gtmId="GTM-XXXXXXX"
|
|
145
|
+
cookieless={true}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Privacy Regulations
|
|
150
|
+
|
|
151
|
+
### GDPR (EU)
|
|
152
|
+
|
|
153
|
+
Requirements:
|
|
154
|
+
- Obtain consent before tracking
|
|
155
|
+
- Provide clear privacy policy
|
|
156
|
+
- Support data access requests
|
|
157
|
+
- Support data deletion requests
|
|
158
|
+
- Minimize data collection
|
|
159
|
+
|
|
160
|
+
### CCPA (California)
|
|
161
|
+
|
|
162
|
+
Requirements:
|
|
163
|
+
- Disclose data collection practices
|
|
164
|
+
- Provide opt-out mechanism
|
|
165
|
+
- Do not sell personal information
|
|
166
|
+
- Respond to consumer requests
|
|
167
|
+
|
|
168
|
+
### PIPEDA (Canada)
|
|
169
|
+
|
|
170
|
+
Requirements:
|
|
171
|
+
- Obtain meaningful consent
|
|
172
|
+
- Limit collection to necessary data
|
|
173
|
+
- Provide access to personal information
|
|
174
|
+
- Protect personal information
|
|
175
|
+
|
|
176
|
+
## Privacy Policy
|
|
177
|
+
|
|
178
|
+
Include in your privacy policy:
|
|
179
|
+
- What data is collected
|
|
180
|
+
- How it's used
|
|
181
|
+
- Third-party services (Google Analytics, GTM)
|
|
182
|
+
- Cookie information
|
|
183
|
+
- User rights and how to exercise them
|
|
184
|
+
- Contact information
|
|
185
|
+
|
|
186
|
+
## Testing Privacy Compliance
|
|
187
|
+
|
|
188
|
+
1. Visit site without consenting - verify no tracking fires
|
|
189
|
+
2. Consent to tracking - verify analytics loads
|
|
190
|
+
3. Decline tracking - verify no analytics cookies set
|
|
191
|
+
4. Clear consent - verify banner reappears
|
|
192
|
+
5. Check no PII in tracked events
|
|
193
|
+
|
|
194
|
+
## See Also
|
|
195
|
+
|
|
196
|
+
- [Analytics Setup](./setup.md)
|
|
197
|
+
- [Tracking Events](./tracking-events.md)
|
|
198
|
+
- [ScriptInjector Component](../../components/ScriptInjector.md)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Analytics Setup
|
|
2
|
+
|
|
3
|
+
Configure analytics tracking for your site.
|
|
4
|
+
|
|
5
|
+
## Google Tag Manager (GTM)
|
|
6
|
+
|
|
7
|
+
### 1. Create GTM Account
|
|
8
|
+
|
|
9
|
+
1. Go to [Google Tag Manager](https://tagmanager.google.com/)
|
|
10
|
+
2. Create new account and container
|
|
11
|
+
3. Copy your GTM ID (format: `GTM-XXXXXXX`)
|
|
12
|
+
|
|
13
|
+
### 2. Add AnalyticsTracker
|
|
14
|
+
|
|
15
|
+
Add to your root layout:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// app/layout.tsx
|
|
19
|
+
import { AnalyticsTracker } from '@zoyth/simple-site-framework/components';
|
|
20
|
+
|
|
21
|
+
export default function RootLayout({ children }) {
|
|
22
|
+
return (
|
|
23
|
+
<html>
|
|
24
|
+
<body>
|
|
25
|
+
<AnalyticsTracker gtmId={process.env.NEXT_PUBLIC_GTM_ID} />
|
|
26
|
+
{children}
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Environment Variables
|
|
34
|
+
|
|
35
|
+
Add GTM ID to environment variables:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# .env.local
|
|
39
|
+
NEXT_PUBLIC_GTM_ID=GTM-XXXXXXX
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Google Analytics 4 (GA4)
|
|
43
|
+
|
|
44
|
+
### Via GTM (Recommended)
|
|
45
|
+
|
|
46
|
+
1. In GTM, create new GA4 Configuration tag
|
|
47
|
+
2. Add your GA4 Measurement ID
|
|
48
|
+
3. Set trigger to "All Pages"
|
|
49
|
+
4. Publish container
|
|
50
|
+
|
|
51
|
+
### Direct Integration
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
<AnalyticsTracker
|
|
55
|
+
gtmId={process.env.NEXT_PUBLIC_GTM_ID}
|
|
56
|
+
gaId={process.env.NEXT_PUBLIC_GA_ID}
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Verification
|
|
61
|
+
|
|
62
|
+
### Check Installation
|
|
63
|
+
|
|
64
|
+
1. Visit your site
|
|
65
|
+
2. Open browser DevTools > Network tab
|
|
66
|
+
3. Look for requests to `gtm.js` or `analytics.js`
|
|
67
|
+
4. Check GTM Preview mode
|
|
68
|
+
5. Verify events in GA4 Realtime view
|
|
69
|
+
|
|
70
|
+
### Debug Mode
|
|
71
|
+
|
|
72
|
+
Enable debug mode in development:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
<AnalyticsTracker
|
|
76
|
+
gtmId={process.env.NEXT_PUBLIC_GTM_ID}
|
|
77
|
+
debug={process.env.NODE_ENV === 'development'}
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Configuration Options
|
|
82
|
+
|
|
83
|
+
| Prop | Type | Required | Description |
|
|
84
|
+
|------|------|----------|-------------|
|
|
85
|
+
| `gtmId` | `string` | Yes* | Google Tag Manager ID |
|
|
86
|
+
| `gaId` | `string` | No | Google Analytics 4 ID |
|
|
87
|
+
| `debug` | `boolean` | No | Enable debug mode |
|
|
88
|
+
| `dataLayer` | `string` | No | Custom dataLayer name (default: 'dataLayer') |
|
|
89
|
+
|
|
90
|
+
*Either gtmId or gaId required
|
|
91
|
+
|
|
92
|
+
## Development vs Production
|
|
93
|
+
|
|
94
|
+
Use different GTM containers:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const gtmId = process.env.NODE_ENV === 'production'
|
|
98
|
+
? process.env.NEXT_PUBLIC_GTM_ID_PROD
|
|
99
|
+
: process.env.NEXT_PUBLIC_GTM_ID_DEV;
|
|
100
|
+
|
|
101
|
+
<AnalyticsTracker gtmId={gtmId} />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Next Steps
|
|
105
|
+
|
|
106
|
+
- [Track custom events](./tracking-events.md)
|
|
107
|
+
- [Set up A/B tests](./ab-testing.md)
|
|
108
|
+
- [Configure conversion tracking](./conversion-tracking.md)
|
|
109
|
+
|
|
110
|
+
## See Also
|
|
111
|
+
|
|
112
|
+
- [Analytics Setup Guide](../../guides/analytics-setup.md)
|
|
113
|
+
- [AnalyticsTracker Component](../../components/AnalyticsTracker.md)
|
|
114
|
+
- [Privacy Configuration](./privacy.md)
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Tracking Events
|
|
2
|
+
|
|
3
|
+
Track user interactions and custom events.
|
|
4
|
+
|
|
5
|
+
## Event Tracking Functions
|
|
6
|
+
|
|
7
|
+
### trackEvent
|
|
8
|
+
|
|
9
|
+
Track generic custom events:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
'use client';
|
|
13
|
+
import { trackEvent } from '@zoyth/simple-site-framework/client';
|
|
14
|
+
|
|
15
|
+
function handleAction() {
|
|
16
|
+
trackEvent('button_click', {
|
|
17
|
+
category: 'engagement',
|
|
18
|
+
label: 'hero_cta',
|
|
19
|
+
value: 1,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### trackPageView
|
|
25
|
+
|
|
26
|
+
Track page views (automatically tracked by AnalyticsTracker):
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { trackPageView } from '@zoyth/simple-site-framework/client';
|
|
30
|
+
|
|
31
|
+
trackPageView('/about');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### trackCTAClick
|
|
35
|
+
|
|
36
|
+
Track call-to-action clicks:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { trackCTAClick } from '@zoyth/simple-site-framework/client';
|
|
40
|
+
|
|
41
|
+
<button onClick={() => trackCTAClick('signup', 'hero')}>
|
|
42
|
+
Sign Up
|
|
43
|
+
</button>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Common Events
|
|
47
|
+
|
|
48
|
+
### Form Submissions
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
function handleSubmit(e) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
|
|
54
|
+
trackEvent('form_submit', {
|
|
55
|
+
form_name: 'contact',
|
|
56
|
+
form_location: 'contact_page',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Handle form...
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Link Clicks
|
|
64
|
+
|
|
65
|
+
Use TrackedLink component:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { TrackedLink } from '@zoyth/simple-site-framework/components';
|
|
69
|
+
|
|
70
|
+
<TrackedLink
|
|
71
|
+
href="/pricing"
|
|
72
|
+
eventName="pricing_link_click"
|
|
73
|
+
eventData={{ location: 'nav' }}
|
|
74
|
+
>
|
|
75
|
+
View Pricing
|
|
76
|
+
</TrackedLink>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Video Interactions
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
function handleVideoPlay() {
|
|
83
|
+
trackEvent('video_play', {
|
|
84
|
+
video_title: 'Product Demo',
|
|
85
|
+
video_duration: 120,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function handleVideoComplete() {
|
|
90
|
+
trackEvent('video_complete', {
|
|
91
|
+
video_title: 'Product Demo',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Scroll Depth
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
'use client';
|
|
100
|
+
import { useEffect } from 'react';
|
|
101
|
+
import { trackEvent } from '@zoyth/simple-site-framework/client';
|
|
102
|
+
|
|
103
|
+
export function ScrollTracker() {
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const depths = [25, 50, 75, 100];
|
|
106
|
+
let tracked = new Set();
|
|
107
|
+
|
|
108
|
+
function handleScroll() {
|
|
109
|
+
const scrollPercent =
|
|
110
|
+
(window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
|
|
111
|
+
|
|
112
|
+
depths.forEach(depth => {
|
|
113
|
+
if (scrollPercent >= depth && !tracked.has(depth)) {
|
|
114
|
+
trackEvent('scroll_depth', { depth });
|
|
115
|
+
tracked.add(depth);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
window.addEventListener('scroll', handleScroll);
|
|
121
|
+
return () => window.removeEventListener('scroll', handleScroll);
|
|
122
|
+
}, []);
|
|
123
|
+
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Event Data Structure
|
|
129
|
+
|
|
130
|
+
Standard event properties:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
trackEvent('event_name', {
|
|
134
|
+
category: 'string', // Event category
|
|
135
|
+
label: 'string', // Event label
|
|
136
|
+
value: number, // Numeric value
|
|
137
|
+
// Custom properties...
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Enhanced E-commerce
|
|
142
|
+
|
|
143
|
+
### Product Clicks
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
trackEvent('select_item', {
|
|
147
|
+
item_list_name: 'Featured Products',
|
|
148
|
+
items: [{
|
|
149
|
+
item_id: 'SKU123',
|
|
150
|
+
item_name: 'Product Name',
|
|
151
|
+
price: 29.99,
|
|
152
|
+
}],
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Add to Cart
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
trackEvent('add_to_cart', {
|
|
160
|
+
currency: 'USD',
|
|
161
|
+
value: 29.99,
|
|
162
|
+
items: [{
|
|
163
|
+
item_id: 'SKU123',
|
|
164
|
+
item_name: 'Product Name',
|
|
165
|
+
price: 29.99,
|
|
166
|
+
quantity: 1,
|
|
167
|
+
}],
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Purchase
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
trackEvent('purchase', {
|
|
175
|
+
transaction_id: 'T12345',
|
|
176
|
+
value: 59.98,
|
|
177
|
+
currency: 'USD',
|
|
178
|
+
items: [{
|
|
179
|
+
item_id: 'SKU123',
|
|
180
|
+
item_name: 'Product Name',
|
|
181
|
+
price: 29.99,
|
|
182
|
+
quantity: 2,
|
|
183
|
+
}],
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## User Timing
|
|
188
|
+
|
|
189
|
+
Track performance metrics:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
trackEvent('timing_complete', {
|
|
193
|
+
name: 'api_request',
|
|
194
|
+
value: 324, // milliseconds
|
|
195
|
+
category: 'performance',
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Error Tracking
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
try {
|
|
203
|
+
// Code that might fail
|
|
204
|
+
} catch (error) {
|
|
205
|
+
trackEvent('exception', {
|
|
206
|
+
description: error.message,
|
|
207
|
+
fatal: false,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Best Practices
|
|
213
|
+
|
|
214
|
+
- Use consistent event naming (snake_case recommended)
|
|
215
|
+
- Include context in event properties
|
|
216
|
+
- Don't track PII (personally identifiable information)
|
|
217
|
+
- Test events in GTM Preview mode
|
|
218
|
+
- Document your event taxonomy
|
|
219
|
+
|
|
220
|
+
## See Also
|
|
221
|
+
|
|
222
|
+
- [Custom Events](./custom-events.md)
|
|
223
|
+
- [Conversion Tracking](./conversion-tracking.md)
|
|
224
|
+
- [TrackedLink Component](../../components/TrackedLink.md)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Internationalization (i18n)
|
|
2
|
+
|
|
3
|
+
Complete guide to multi-language support in Simple Site Framework.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Simple Site Framework provides built-in internationalization (i18n) support for creating multi-language websites with:
|
|
8
|
+
|
|
9
|
+
- Configurable locale routing (always, as-needed, never)
|
|
10
|
+
- LocalizedString type for content translation
|
|
11
|
+
- Automatic language detection
|
|
12
|
+
- SEO-optimized language alternates
|
|
13
|
+
- RTL language support
|
|
14
|
+
- Locale-aware formatting (dates, numbers, currency)
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
// Configure locales
|
|
20
|
+
export const i18nConfig = {
|
|
21
|
+
locales: ['en', 'fr', 'es'],
|
|
22
|
+
defaultLocale: 'en',
|
|
23
|
+
localePrefix: 'as-needed',
|
|
24
|
+
localeDetection: true,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Use LocalizedString
|
|
28
|
+
const heading = {
|
|
29
|
+
en: 'Welcome',
|
|
30
|
+
fr: 'Bienvenue',
|
|
31
|
+
es: 'Bienvenido',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
<HeroSection heading={heading} locale={locale} />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Topics
|
|
38
|
+
|
|
39
|
+
- [Configuration](./configuration.md) - Setting up i18n config
|
|
40
|
+
- [Routing](./routing.md) - Locale routing and URL structure
|
|
41
|
+
- [Translations](./translations.md) - Managing translated content
|
|
42
|
+
- [Locale Detection](./locale-detection.md) - Browser and cookie detection
|
|
43
|
+
- [Formatting](./formatting.md) - Date, number, currency formatting
|
|
44
|
+
- [RTL Support](./rtl-support.md) - Right-to-left language support
|
|
45
|
+
- [Best Practices](./best-practices.md) - i18n patterns and tips
|
|
46
|
+
|
|
47
|
+
## See Also
|
|
48
|
+
|
|
49
|
+
- [Internationalization Feature Guide](../internationalization.md)
|
|
50
|
+
- [LanguageSelector Component](../../components/layout/LanguageSelector.md)
|
|
51
|
+
- [I18nMetaTags Component](../../components/I18nMetaTags.md)
|