chore(analytics): completely scrub NEXT_PUBLIC prefix from umami website id across codebase and docs
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 1m14s
Build & Deploy / 🧪 QA (push) Successful in 3m20s
Build & Deploy / 🧪 Smoke Test (push) Failing after 49s
Build & Deploy / ⚡ Lighthouse (push) Successful in 3m24s
Build & Deploy / 🏗️ Build (push) Successful in 3m2s
Build & Deploy / 🚀 Deploy (push) Successful in 26s
Build & Deploy / 🔔 Notify (push) Successful in 2s

This commit is contained in:
2026-02-20 15:29:50 +01:00
parent 23bf327670
commit c646815a3a
10 changed files with 147 additions and 157 deletions

View File

@@ -136,18 +136,14 @@ function AddToCartButton({ product, quantity = 1 }) {
product_category: product.category, product_category: product.category,
price: product.price, price: product.price,
quantity: quantity, quantity: quantity,
cart_total: 150.00, // Current cart total cart_total: 150.0, // Current cart total
}); });
// Actual add to cart logic // Actual add to cart logic
// addToCart(product, quantity); // addToCart(product, quantity);
}; };
return ( return <button onClick={handleAddToCart}>Add to Cart</button>;
<button onClick={handleAddToCart}>
Add to Cart
</button>
);
} }
``` ```
@@ -171,7 +167,7 @@ function CheckoutComplete({ order }) {
transaction_tax: order.tax, transaction_tax: order.tax,
transaction_shipping: order.shipping, transaction_shipping: order.shipping,
product_count: order.items.length, product_count: order.items.length,
products: order.items.map(item => ({ products: order.items.map((item) => ({
product_id: item.product.id, product_id: item.product.id,
product_name: item.product.name, product_name: item.product.name,
quantity: item.quantity, quantity: item.quantity,
@@ -200,25 +196,19 @@ function WishlistButton({ product }) {
const newState = !isInWishlist; const newState = !isInWishlist;
trackEvent( trackEvent(
newState newState ? AnalyticsEvents.PRODUCT_WISHLIST_ADD : AnalyticsEvents.PRODUCT_WISHLIST_REMOVE,
? AnalyticsEvents.PRODUCT_WISHLIST_ADD
: AnalyticsEvents.PRODUCT_WISHLIST_REMOVE,
{ {
product_id: product.id, product_id: product.id,
product_name: product.name, product_name: product.name,
product_category: product.category, product_category: product.category,
} },
); );
setIsInWishlist(newState); setIsInWishlist(newState);
// Update wishlist in backend // Update wishlist in backend
}; };
return ( return <button onClick={toggleWishlist}>{isInWishlist ? '❤️' : '🤍'}</button>;
<button onClick={toggleWishlist}>
{isInWishlist ? '❤️' : '🤍'}
</button>
);
} }
``` ```
@@ -268,7 +258,7 @@ function ContactForm() {
}; };
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormData(prev => ({ setFormData((prev) => ({
...prev, ...prev,
[e.target.name]: e.target.value, [e.target.name]: e.target.value,
})); }));
@@ -310,9 +300,7 @@ function NewsletterSignup() {
return ( return (
<div> <div>
<input placeholder="Enter email" /> <input placeholder="Enter email" />
<button onClick={() => handleSubscribe('user@example.com')}> <button onClick={() => handleSubscribe('user@example.com')}>Subscribe</button>
Subscribe
</button>
</div> </div>
); );
} }
@@ -396,10 +384,12 @@ function LoginForm() {
}; };
return ( return (
<form onSubmit={(e) => { <form
e.preventDefault(); onSubmit={(e) => {
handleLogin('user@example.com', 'password'); e.preventDefault();
}}> handleLogin('user@example.com', 'password');
}}
>
{/* Form fields */} {/* Form fields */}
<button type="submit">Login</button> <button type="submit">Login</button>
</form> </form>
@@ -418,11 +408,7 @@ import { AnalyticsEvents } from '@/components/analytics/analytics-events';
function SignupForm() { function SignupForm() {
const { trackEvent } = useAnalytics(); const { trackEvent } = useAnalytics();
const handleSignup = (userData: { const handleSignup = (userData: { email: string; name: string; company?: string }) => {
email: string;
name: string;
company?: string;
}) => {
trackEvent(AnalyticsEvents.USER_SIGNUP, { trackEvent(AnalyticsEvents.USER_SIGNUP, {
user_email: userData.email, user_email: userData.email,
user_name: userData.name, user_name: userData.name,
@@ -436,14 +422,16 @@ function SignupForm() {
}; };
return ( return (
<form onSubmit={(e) => { <form
e.preventDefault(); onSubmit={(e) => {
handleSignup({ e.preventDefault();
email: 'user@example.com', handleSignup({
name: 'John Doe', email: 'user@example.com',
company: 'ACME Corp', name: 'John Doe',
}); company: 'ACME Corp',
}}> });
}}
>
{/* Form fields */} {/* Form fields */}
<button type="submit">Sign Up</button> <button type="submit">Sign Up</button>
</form> </form>
@@ -631,11 +619,7 @@ function VideoPlayer({ videoId, videoTitle }) {
}; };
return ( return (
<video <video onPlay={handlePlay} onPause={handlePause} onEnded={handleComplete}>
onPlay={handlePlay}
onPause={handlePause}
onEnded={handleComplete}
>
<source src="/video.mp4" type="video/mp4" /> <source src="/video.mp4" type="video/mp4" />
</video> </video>
); );
@@ -665,11 +649,7 @@ function DownloadButton({ fileName, fileType, fileSize }) {
// window.location.href = `/downloads/${fileName}`; // window.location.href = `/downloads/${fileName}`;
}; };
return ( return <button onClick={handleDownload}>Download {fileName}</button>;
<button onClick={handleDownload}>
Download {fileName}
</button>
);
} }
``` ```
@@ -963,15 +943,9 @@ function CableProductPage({ cable }) {
return ( return (
<div> <div>
<h1>{cable.name}</h1> <h1>{cable.name}</h1>
<button onClick={handleTechnicalSpecDownload}> <button onClick={handleTechnicalSpecDownload}>Download Technical Specs</button>
Download Technical Specs <button onClick={handleRequestQuote}>Request Quote</button>
</button> <button onClick={handleBrochureDownload}>Download Brochure</button>
<button onClick={handleRequestQuote}>
Request Quote
</button>
<button onClick={handleBrochureDownload}>
Download Brochure
</button>
</div> </div>
); );
} }
@@ -1010,12 +984,8 @@ function WindFarmProjectPage({ project }) {
return ( return (
<div> <div>
<h1>{project.name}</h1> <h1>{project.name}</h1>
<button onClick={handleProjectInquiry}> <button onClick={handleProjectInquiry}>Request Project Consultation</button>
Request Project Consultation <button onClick={handleCableCalculation}>Calculate Cable Requirements</button>
</button>
<button onClick={handleCableCalculation}>
Calculate Cable Requirements
</button>
</div> </div>
); );
} }
@@ -1066,7 +1036,7 @@ test('tracks button click', () => {
// [Umami] Tracked pageview: /products/123 // [Umami] Tracked pageview: /products/123
// To test without sending data to Umami: // To test without sending data to Umami:
// 1. Remove NEXT_PUBLIC_UMAMI_WEBSITE_ID from .env // 1. Remove UMAMI_WEBSITE_ID from .env
// 2. Or set it to an empty string // 2. Or set it to an empty string
// 3. Check console logs to verify events are being tracked // 3. Check console logs to verify events are being tracked
``` ```
@@ -1169,7 +1139,9 @@ function WebVitalsTracker() {
} }
}); });
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input-delay', 'layout-shift'] }); observer.observe({
entryTypes: ['largest-contentful-paint', 'first-input-delay', 'layout-shift'],
});
} }
}, []); }, []);
@@ -1194,6 +1166,7 @@ This examples file demonstrates how to implement comprehensive analytics trackin
-**Business-specific events** (KLZ Cables, wind farms) -**Business-specific events** (KLZ Cables, wind farms)
Remember to: Remember to:
1. Use the `useAnalytics` hook for client-side tracking 1. Use the `useAnalytics` hook for client-side tracking
2. Import events from `AnalyticsEvents` for consistency 2. Import events from `AnalyticsEvents` for consistency
3. Include relevant context in your events 3. Include relevant context in your events

View File

@@ -2,7 +2,7 @@
## Setup Checklist ## Setup Checklist
- [ ] Add `NEXT_PUBLIC_UMAMI_WEBSITE_ID` to `.env` file - [ ] Add `UMAMI_WEBSITE_ID` to `.env` file
- [ ] Verify `UmamiScript` is in your layout - [ ] Verify `UmamiScript` is in your layout
- [ ] Verify `AnalyticsProvider` is in your layout - [ ] Verify `AnalyticsProvider` is in your layout
- [ ] Test in development mode - [ ] Test in development mode
@@ -12,7 +12,7 @@
```bash ```bash
# Required # Required
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3 UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
# Optional (defaults to https://analytics.infra.mintel.me/script.js) # Optional (defaults to https://analytics.infra.mintel.me/script.js)
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
@@ -86,16 +86,16 @@ function ProductCard({ product }) {
## Common Events ## Common Events
| Event | When to Use | Example Properties | | Event | When to Use | Example Properties |
|-------|-------------|-------------------| | --------------------- | ------------------- | ------------------------------------------------- |
| `pageview` | Page loads | `{ url: '/products/123' }` | | `pageview` | Page loads | `{ url: '/products/123' }` |
| `button_click` | Button clicked | `{ button_id: 'cta', page: 'homepage' }` | | `button_click` | Button clicked | `{ button_id: 'cta', page: 'homepage' }` |
| `form_submit` | Form submitted | `{ form_id: 'contact', form_name: 'Contact Us' }` | | `form_submit` | Form submitted | `{ form_id: 'contact', form_name: 'Contact Us' }` |
| `product_view` | Product page viewed | `{ product_id: '123', price: 99.99 }` | | `product_view` | Product page viewed | `{ product_id: '123', price: 99.99 }` |
| `product_add_to_cart` | Add to cart | `{ product_id: '123', quantity: 1 }` | | `product_add_to_cart` | Add to cart | `{ product_id: '123', quantity: 1 }` |
| `search` | Search performed | `{ search_query: 'cable', results: 42 }` | | `search` | Search performed | `{ search_query: 'cable', results: 42 }` |
| `user_login` | User logged in | `{ user_email: 'user@example.com' }` | | `user_login` | User logged in | `{ user_email: 'user@example.com' }` |
| `error` | Error occurred | `{ error_message: 'Something went wrong' }` | | `error` | Error occurred | `{ error_message: 'Something went wrong' }` |
## Testing ## Testing
@@ -112,7 +112,7 @@ In development, you'll see console logs:
```bash ```bash
# .env.local # .env.local
# NEXT_PUBLIC_UMAMI_WEBSITE_ID= # UMAMI_WEBSITE_ID=
``` ```
## Troubleshooting ## Troubleshooting
@@ -120,8 +120,9 @@ In development, you'll see console logs:
### Analytics Not Working? ### Analytics Not Working?
1. **Check environment variables:** 1. **Check environment variables:**
```bash ```bash
echo $NEXT_PUBLIC_UMAMI_WEBSITE_ID echo $UMAMI_WEBSITE_ID
``` ```
2. **Verify script is loading:** 2. **Verify script is loading:**
@@ -136,12 +137,12 @@ In development, you'll see console logs:
### Common Issues ### Common Issues
| Issue | Solution | | Issue | Solution |
|-------|----------| | ------------------- | ----------------------------------- |
| No data in Umami | Check website ID and script URL | | No data in Umami | Check website ID and script URL |
| Events not tracking | Verify `useAnalytics` hook is used | | Events not tracking | Verify `useAnalytics` hook is used |
| Script not loading | Check network connection, CORS | | Script not loading | Check network connection, CORS |
| Wrong data | Verify event properties are correct | | Wrong data | Verify event properties are correct |
## Performance Tips ## Performance Tips

View File

@@ -20,7 +20,7 @@ Add these to your `.env` file:
```bash ```bash
# Required: Your Umami website ID # Required: Your Umami website ID
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3 UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
# Optional: Custom Umami script URL (defaults to https://analytics.infra.mintel.me/script.js) # Optional: Custom Umami script URL (defaults to https://analytics.infra.mintel.me/script.js)
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
@@ -32,7 +32,7 @@ The `docker-compose.yml` already includes the environment variables:
```yaml ```yaml
environment: environment:
- NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID} - UMAMI_WEBSITE_ID=${UMAMI_WEBSITE_ID}
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js} - NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js}
``` ```
@@ -75,11 +75,7 @@ function ProductCard({ product }) {
}); });
}; };
return ( return <button onClick={handleAddToCart}>Add to Cart</button>;
<button onClick={handleAddToCart}>
Add to Cart
</button>
);
} }
``` ```
@@ -277,11 +273,7 @@ function ErrorBoundary({ children }) {
}); });
}; };
return ( return <ErrorBoundary onError={handleError}>{children}</ErrorBoundary>;
<ErrorBoundary onError={handleError}>
{children}
</ErrorBoundary>
);
} }
``` ```
@@ -289,20 +281,20 @@ function ErrorBoundary({ children }) {
### Common Events ### Common Events
| Event Name | Description | Example Properties | | Event Name | Description | Example Properties |
|------------|-------------|-------------------| | --------------------- | --------------------- | ------------------------------------------------------------ |
| `pageview` | Page view | `{ url: '/products/123' }` | | `pageview` | Page view | `{ url: '/products/123' }` |
| `button_click` | Button clicked | `{ button_id: 'cta-primary', page: 'homepage' }` | | `button_click` | Button clicked | `{ button_id: 'cta-primary', page: 'homepage' }` |
| `link_click` | Link clicked | `{ link_url: '/products', link_text: 'View Products' }` | | `link_click` | Link clicked | `{ link_url: '/products', link_text: 'View Products' }` |
| `form_submit` | Form submitted | `{ form_id: 'contact-form', form_name: 'Contact Us' }` | | `form_submit` | Form submitted | `{ form_id: 'contact-form', form_name: 'Contact Us' }` |
| `product_view` | Product page viewed | `{ product_id: '123', product_name: 'Cable', price: 99.99 }` | | `product_view` | Product page viewed | `{ product_id: '123', product_name: 'Cable', price: 99.99 }` |
| `product_add_to_cart` | Product added to cart | `{ product_id: '123', quantity: 1 }` | | `product_add_to_cart` | Product added to cart | `{ product_id: '123', quantity: 1 }` |
| `product_purchase` | Product purchased | `{ product_id: '123', transaction_id: 'TXN-123' }` | | `product_purchase` | Product purchased | `{ product_id: '123', transaction_id: 'TXN-123' }` |
| `search` | Search performed | `{ search_query: 'cable', search_results_count: 42 }` | | `search` | Search performed | `{ search_query: 'cable', search_results_count: 42 }` |
| `filter_apply` | Filter applied | `{ filter_type: 'category', filter_value: 'high-voltage' }` | | `filter_apply` | Filter applied | `{ filter_type: 'category', filter_value: 'high-voltage' }` |
| `user_login` | User logged in | `{ user_email: 'user@example.com' }` | | `user_login` | User logged in | `{ user_email: 'user@example.com' }` |
| `user_signup` | User signed up | `{ user_email: 'user@example.com' }` | | `user_signup` | User signed up | `{ user_email: 'user@example.com' }` |
| `error` | Error occurred | `{ error_message: 'Something went wrong' }` | | `error` | Error occurred | `{ error_message: 'Something went wrong' }` |
### Custom Events ### Custom Events
@@ -385,8 +377,9 @@ The analytics system includes development mode logging:
### Analytics Not Working ### Analytics Not Working
1. **Check environment variables:** 1. **Check environment variables:**
```bash ```bash
echo $NEXT_PUBLIC_UMAMI_WEBSITE_ID echo $UMAMI_WEBSITE_ID
``` ```
2. **Verify the script is loading:** 2. **Verify the script is loading:**
@@ -405,11 +398,11 @@ In development mode, you'll see console logs for all tracked events. This helps
### Disabling Analytics ### Disabling Analytics
To disable analytics (e.g., for local development), simply remove the `NEXT_PUBLIC_UMAMI_WEBSITE_ID` environment variable: To disable analytics (e.g., for local development), simply remove the `UMAMI_WEBSITE_ID` environment variable:
```bash ```bash
# .env.local (not committed to git) # .env.local (not committed to git)
# NEXT_PUBLIC_UMAMI_WEBSITE_ID= # UMAMI_WEBSITE_ID=
``` ```
## Performance ## Performance
@@ -438,6 +431,7 @@ The analytics implementation is optimized for performance:
## Support ## Support
For issues or questions about the analytics implementation, check: For issues or questions about the analytics implementation, check:
1. This README for usage examples 1. This README for usage examples
2. The component source code for implementation details 2. The component source code for implementation details
3. The Umami documentation for platform-specific questions 3. The Umami documentation for platform-specific questions

View File

@@ -16,6 +16,7 @@ The project already had a solid foundation:
## What Was Enhanced ## What Was Enhanced
### 1. **Enhanced UmamiScript** (`components/analytics/UmamiScript.tsx`) ### 1. **Enhanced UmamiScript** (`components/analytics/UmamiScript.tsx`)
- ✅ Added TypeScript props interface for customization - ✅ Added TypeScript props interface for customization
- ✅ Added JSDoc documentation with usage examples - ✅ Added JSDoc documentation with usage examples
- ✅ Added error handling for script loading failures - ✅ Added error handling for script loading failures
@@ -23,11 +24,13 @@ The project already had a solid foundation:
- ✅ Improved type safety and comments - ✅ Improved type safety and comments
### 2. **Enhanced AnalyticsProvider** (`components/analytics/AnalyticsProvider.tsx`) ### 2. **Enhanced AnalyticsProvider** (`components/analytics/AnalyticsProvider.tsx`)
- ✅ Added comprehensive JSDoc documentation - ✅ Added comprehensive JSDoc documentation
- ✅ Added development mode logging - ✅ Added development mode logging
- ✅ Improved code comments - ✅ Improved code comments
### 3. **New Custom Hook** (`components/analytics/useAnalytics.ts`) ### 3. **New Custom Hook** (`components/analytics/useAnalytics.ts`)
- ✅ Type-safe `useAnalytics` hook for easy event tracking - ✅ Type-safe `useAnalytics` hook for easy event tracking
-`trackEvent()` method for custom events -`trackEvent()` method for custom events
-`trackPageview()` method for manual pageview tracking -`trackPageview()` method for manual pageview tracking
@@ -35,12 +38,14 @@ The project already had a solid foundation:
- ✅ Development mode logging - ✅ Development mode logging
### 4. **Event Definitions** (`components/analytics/analytics-events.ts`) ### 4. **Event Definitions** (`components/analytics/analytics-events.ts`)
- ✅ Centralized event constants for consistency - ✅ Centralized event constants for consistency
- ✅ Type-safe event names - ✅ Type-safe event names
- ✅ Helper functions for common event properties - ✅ Helper functions for common event properties
- ✅ 30+ predefined events for various use cases - ✅ 30+ predefined events for various use cases
### 5. **Comprehensive Documentation** ### 5. **Comprehensive Documentation**
-**README.md** - Full documentation with setup, usage, and best practices -**README.md** - Full documentation with setup, usage, and best practices
-**EXAMPLES.md** - 20+ practical examples for different scenarios -**EXAMPLES.md** - 20+ practical examples for different scenarios
-**QUICK_REFERENCE.md** - Quick start guide and troubleshooting -**QUICK_REFERENCE.md** - Quick start guide and troubleshooting
@@ -63,12 +68,14 @@ components/analytics/
## Key Features ## Key Features
### 🚀 Modern Implementation ### 🚀 Modern Implementation
- Uses Next.js `Script` component (not old-school `<script>` tags) - Uses Next.js `Script` component (not old-school `<script>` tags)
- TypeScript for type safety - TypeScript for type safety
- React hooks for clean API - React hooks for clean API
- Environment variable configuration - Environment variable configuration
### 📊 Comprehensive Tracking ### 📊 Comprehensive Tracking
- Automatic pageview tracking on route changes - Automatic pageview tracking on route changes
- Custom event tracking with properties - Custom event tracking with properties
- E-commerce events (products, cart, purchases) - E-commerce events (products, cart, purchases)
@@ -77,6 +84,7 @@ components/analytics/
- Error and performance tracking - Error and performance tracking
### 🎯 Developer Experience ### 🎯 Developer Experience
- Type-safe event tracking - Type-safe event tracking
- Centralized event definitions - Centralized event definitions
- Development mode logging - Development mode logging
@@ -84,6 +92,7 @@ components/analytics/
- 20+ practical examples - 20+ practical examples
### 🔒 Privacy & Performance ### 🔒 Privacy & Performance
- No PII tracking by default - No PII tracking by default
- Script loads after page is interactive - Script loads after page is interactive
- Minimal performance impact - Minimal performance impact
@@ -95,7 +104,7 @@ The project is already configured in `docker-compose.yml`:
```yaml ```yaml
environment: environment:
- NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID} - UMAMI_WEBSITE_ID=${UMAMI_WEBSITE_ID}
- NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js} - NEXT_PUBLIC_UMAMI_SCRIPT_URL=${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-https://analytics.infra.mintel.me/script.js}
``` ```
@@ -104,7 +113,7 @@ environment:
Add to your `.env` file: Add to your `.env` file:
```bash ```bash
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3 UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
``` ```
## Usage Examples ## Usage Examples
@@ -188,7 +197,7 @@ In development, you'll see console logs:
```bash ```bash
# .env.local # .env.local
# NEXT_PUBLIC_UMAMI_WEBSITE_ID= # UMAMI_WEBSITE_ID=
``` ```
## Troubleshooting ## Troubleshooting
@@ -196,8 +205,9 @@ In development, you'll see console logs:
### Analytics Not Working? ### Analytics Not Working?
1. **Check environment variables:** 1. **Check environment variables:**
```bash ```bash
echo $NEXT_PUBLIC_UMAMI_WEBSITE_ID echo $UMAMI_WEBSITE_ID
``` ```
2. **Verify script is loading:** 2. **Verify script is loading:**
@@ -212,12 +222,12 @@ In development, you'll see console logs:
### Common Issues ### Common Issues
| Issue | Solution | | Issue | Solution |
|-------|----------| | ------------------- | ----------------------------------- |
| No data in Umami | Check website ID and script URL | | No data in Umami | Check website ID and script URL |
| Events not tracking | Verify `useAnalytics` hook is used | | Events not tracking | Verify `useAnalytics` hook is used |
| Script not loading | Check network connection, CORS | | Script not loading | Check network connection, CORS |
| Wrong data | Verify event properties are correct | | Wrong data | Verify event properties are correct |
## Performance Tips ## Performance Tips
@@ -239,13 +249,13 @@ In development, you'll see console logs:
1. ✅ **Setup complete** - All files are in place 1. ✅ **Setup complete** - All files are in place
2. ✅ **Documentation complete** - README, EXAMPLES, QUICK_REFERENCE 2. ✅ **Documentation complete** - README, EXAMPLES, QUICK_REFERENCE
3. ✅ **Code enhanced** - Better TypeScript, error handling, docs 3. ✅ **Code enhanced** - Better TypeScript, error handling, docs
4. 📝 **Add to .env** - Set `NEXT_PUBLIC_UMAMI_WEBSITE_ID` 4. 📝 **Add to .env** - Set `UMAMI_WEBSITE_ID`
5. 🧪 **Test in development** - Verify events are tracked 5. 🧪 **Test in development** - Verify events are tracked
6. 🚀 **Deploy** - Analytics will work in production 6. 🚀 **Deploy** - Analytics will work in production
## Quick Start Checklist ## Quick Start Checklist
- [ ] Add `NEXT_PUBLIC_UMAMI_WEBSITE_ID` to `.env` file - [ ] Add `UMAMI_WEBSITE_ID` to `.env` file
- [ ] Verify `UmamiScript` is in `app/[locale]/layout.tsx` - [ ] Verify `UmamiScript` is in `app/[locale]/layout.tsx`
- [ ] Verify `AnalyticsProvider` is in `app/[locale]/layout.tsx` - [ ] Verify `AnalyticsProvider` is in `app/[locale]/layout.tsx`
- [ ] Test in development mode (check console logs) - [ ] Test in development mode (check console logs)

View File

@@ -39,7 +39,7 @@ NODE_ENV=production
NEXT_PUBLIC_BASE_URL=https://klz-cables.com NEXT_PUBLIC_BASE_URL=https://klz-cables.com
# Analytics (Umami) # Analytics (Umami)
NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-umami-website-id UMAMI_WEBSITE_ID=your-umami-website-id
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
# Error Tracking (GlitchTip/Sentry) # Error Tracking (GlitchTip/Sentry)

View File

@@ -35,7 +35,7 @@ function createConfig() {
analytics: { analytics: {
umami: { umami: {
websiteId: env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || env.UMAMI_WEBSITE_ID, websiteId: env.UMAMI_WEBSITE_ID,
apiEndpoint: env.UMAMI_API_ENDPOINT || 'https://analytics.infra.mintel.me', apiEndpoint: env.UMAMI_API_ENDPOINT || 'https://analytics.infra.mintel.me',
enabled: typeof window !== 'undefined' || Boolean(env.UMAMI_WEBSITE_ID), enabled: typeof window !== 'undefined' || Boolean(env.UMAMI_WEBSITE_ID),
}, },

View File

@@ -31,7 +31,7 @@ const envExtension = {
INFRA_DIRECTUS_TOKEN: z.string().optional(), INFRA_DIRECTUS_TOKEN: z.string().optional(),
// Analytics // Analytics
NEXT_PUBLIC_UMAMI_WEBSITE_ID: z.string().optional(), UMAMI_WEBSITE_ID: z.string().optional(),
UMAMI_API_ENDPOINT: z.string().optional(), UMAMI_API_ENDPOINT: z.string().optional(),
// Mail Configuration // Mail Configuration

View File

@@ -30,6 +30,7 @@ export interface AnalyticsService {
``` ```
**Key Features:** **Key Features:**
- Type-safe event properties - Type-safe event properties
- Consistent API across implementations - Consistent API across implementations
- Well-documented with JSDoc comments - Well-documented with JSDoc comments
@@ -39,6 +40,7 @@ export interface AnalyticsService {
Implements the `AnalyticsService` interface for Umami analytics. Implements the `AnalyticsService` interface for Umami analytics.
**Features:** **Features:**
- Type-safe event tracking - Type-safe event tracking
- Automatic pageview tracking - Automatic pageview tracking
- Browser environment detection - Browser environment detection
@@ -46,6 +48,7 @@ Implements the `AnalyticsService` interface for Umami analytics.
- Comprehensive JSDoc documentation - Comprehensive JSDoc documentation
**Usage:** **Usage:**
```typescript ```typescript
import { UmamiAnalyticsService } from '@/lib/services/analytics/umami-analytics-service'; import { UmamiAnalyticsService } from '@/lib/services/analytics/umami-analytics-service';
@@ -59,12 +62,14 @@ service.trackPageview('/products/123');
A no-op implementation used as a fallback when analytics are disabled. A no-op implementation used as a fallback when analytics are disabled.
**Features:** **Features:**
- Maintains the same API as other services - Maintains the same API as other services
- Safe to call even when analytics are disabled - Safe to call even when analytics are disabled
- No performance impact - No performance impact
- Comprehensive JSDoc documentation - Comprehensive JSDoc documentation
**Usage:** **Usage:**
```typescript ```typescript
import { NoopAnalyticsService } from '@/lib/services/analytics/noop-analytics-service'; import { NoopAnalyticsService } from '@/lib/services/analytics/noop-analytics-service';
@@ -79,7 +84,7 @@ The service layer automatically selects the appropriate implementation based on
```typescript ```typescript
// In lib/services/create-services.ts // In lib/services/create-services.ts
const umamiEnabled = Boolean(process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID); const umamiEnabled = Boolean(process.env.UMAMI_WEBSITE_ID);
const analytics = umamiEnabled const analytics = umamiEnabled
? new UmamiAnalyticsService({ enabled: true }) ? new UmamiAnalyticsService({ enabled: true })
@@ -91,7 +96,7 @@ const analytics = umamiEnabled
### Required for Umami ### Required for Umami
```bash ```bash
NEXT_PUBLIC_UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3 UMAMI_WEBSITE_ID=59a7db94-0100-4c7e-98ef-99f45b17f9c3
``` ```
### Optional (defaults provided) ### Optional (defaults provided)
@@ -109,10 +114,12 @@ NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
Track a custom event with optional properties. Track a custom event with optional properties.
**Parameters:** **Parameters:**
- `eventName` - The name of the event to track - `eventName` - The name of the event to track
- `props` - Optional event properties (metadata) - `props` - Optional event properties (metadata)
**Example:** **Example:**
```typescript ```typescript
service.track('product_add_to_cart', { service.track('product_add_to_cart', {
product_id: '123', product_id: '123',
@@ -127,9 +134,11 @@ service.track('product_add_to_cart', {
Track a pageview. Track a pageview.
**Parameters:** **Parameters:**
- `url` - The URL to track (defaults to current location) - `url` - The URL to track (defaults to current location)
**Example:** **Example:**
```typescript ```typescript
// Track current page // Track current page
service.trackPageview(); service.trackPageview();
@@ -147,9 +156,11 @@ new UmamiAnalyticsService(options: UmamiAnalyticsServiceOptions)
``` ```
**Options:** **Options:**
- `enabled: boolean` - Whether analytics are enabled - `enabled: boolean` - Whether analytics are enabled
**Example:** **Example:**
```typescript ```typescript
const service = new UmamiAnalyticsService({ enabled: true }); const service = new UmamiAnalyticsService({ enabled: true });
``` ```
@@ -159,10 +170,11 @@ const service = new UmamiAnalyticsService({ enabled: true });
#### Constructor #### Constructor
```typescript ```typescript
new NoopAnalyticsService() new NoopAnalyticsService();
``` ```
**Example:** **Example:**
```typescript ```typescript
const service = new NoopAnalyticsService(); const service = new NoopAnalyticsService();
``` ```
@@ -172,13 +184,11 @@ const service = new NoopAnalyticsService();
### AnalyticsEventProperties ### AnalyticsEventProperties
```typescript ```typescript
type AnalyticsEventProperties = Record< type AnalyticsEventProperties = Record<string, string | number | boolean | null | undefined>;
string,
string | number | boolean | null | undefined
>;
``` ```
**Example:** **Example:**
```typescript ```typescript
const properties: AnalyticsEventProperties = { const properties: AnalyticsEventProperties = {
product_id: '123', product_id: '123',
@@ -253,7 +263,7 @@ services.analytics.track('button_click', {
The service layer gracefully handles disabled analytics: The service layer gracefully handles disabled analytics:
```typescript ```typescript
// When NEXT_PUBLIC_UMAMI_WEBSITE_ID is not set: // When UMAMI_WEBSITE_ID is not set:
// - NoopAnalyticsService is used // - NoopAnalyticsService is used
// - All calls are safe (no-op) // - All calls are safe (no-op)
// - No errors are thrown // - No errors are thrown
@@ -382,11 +392,13 @@ async function MyServerComponent() {
### Analytics Not Working ### Analytics Not Working
1. **Check environment variables:** 1. **Check environment variables:**
```bash ```bash
echo $NEXT_PUBLIC_UMAMI_WEBSITE_ID echo $UMAMI_WEBSITE_ID
``` ```
2. **Verify service selection:** 2. **Verify service selection:**
```typescript ```typescript
import { getAppServices } from '@/lib/services/create-services'; import { getAppServices } from '@/lib/services/create-services';
@@ -401,12 +413,12 @@ async function MyServerComponent() {
### Common Issues ### Common Issues
| Issue | Solution | | Issue | Solution |
|-------|----------| | ------------------- | ----------------------------------- |
| No data in Umami | Check website ID and script URL | | No data in Umami | Check website ID and script URL |
| Events not tracking | Verify service is being used | | Events not tracking | Verify service is being used |
| Script not loading | Check network connection, CORS | | Script not loading | Check network connection, CORS |
| Wrong data | Verify event properties are correct | | Wrong data | Verify event properties are correct |
## Related Files ## Related Files

View File

@@ -19,7 +19,7 @@ import type { AnalyticsEventProperties, AnalyticsService } from './analytics-ser
* @example * @example
* ```typescript * ```typescript
* // Automatic fallback in create-services.ts * // Automatic fallback in create-services.ts
* const umamiEnabled = Boolean(process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID); * const umamiEnabled = Boolean(process.env.UMAMI_WEBSITE_ID);
* const analytics = umamiEnabled * const analytics = umamiEnabled
* ? new UmamiAnalyticsService({ enabled: true }) * ? new UmamiAnalyticsService({ enabled: true })
* : new NoopAnalyticsService(); // Fallback when no website ID * : new NoopAnalyticsService(); // Fallback when no website ID

View File

@@ -55,7 +55,7 @@ let singleton: AppServices | undefined;
* @example * @example
* ```typescript * ```typescript
* // Automatic service selection based on environment * // Automatic service selection based on environment
* // If NEXT_PUBLIC_UMAMI_WEBSITE_ID is set: * // If UMAMI_WEBSITE_ID is set:
* // services.analytics = UmamiAnalyticsService * // services.analytics = UmamiAnalyticsService
* // If not set: * // If not set:
* // services.analytics = NoopAnalyticsService (safe no-op) * // services.analytics = NoopAnalyticsService (safe no-op)