# UTM Cleanup Architecture

**Last Updated:** 2026-01-29

## Architecture Overview

UTM parameter cleaning is implemented client-side using JavaScript to remove tracking parameters from URLs after analytics tools have captured them.

## Component Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    Page Load                                 │
│  URL: /page?utm_source=test&utm_campaign=test              │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│              UTM Tracker Initialization                      │
│  - Extract UTMs from URL                                     │
│  - Store in instance variables                               │
│  - Set cookies (90-day expiration)                          │
│  - Store in localStorage (fallback)                         │
│  - Store original URL                                        │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│            Analytics Scripts Load                            │
│  - GTM loads (async)                                         │
│  - GA4 fires via GTM                                         │
│  - HubSpot loads (async defer)                               │
│  - All capture UTMs from URL                                │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│         Wait for Analytics Ready                             │
│  - Check GTM dataLayer                                       │
│  - Check HubSpot script                                      │
│  - Check page load state                                      │
│  - Proceed when ready OR after 1.5s minimum                │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│              Cleanup Execution                               │
│  - Remove utm_* parameters                                   │
│  - Remove gclid, leadSource, etc.                            │
│  - Preserve hsa_* parameters                                 │
│  - Update URL via history.replaceState()                     │
│  - Dispatch utmCleanupComplete event                         │
│  - Send to dataLayer for monitoring                          │
└─────────────────────┬───────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────────────────┐
│            Clean URL Displayed                                │
│  URL: /page?hsa_src=g&hsa_cam=123                           │
│  (UTMs removed, hsa_* preserved)                            │
└─────────────────────────────────────────────────────────────┘
```

## Data Flow

### 1. Page Load
- UTMs extracted from URL
- Stored in instance variables (`this.utm_source`, etc.)
- Cookies set immediately
- localStorage set as fallback
- Original URL stored

### 2. Analytics Capture
- GTM/GA4 read from URL
- HubSpot reads from URL (may be async)
- All capture UTMs before cleanup

### 3. Cleanup Execution
- Wait for analytics ready
- Remove UTMs from URL
- Preserve hsa_* parameters
- Update browser history
- Dispatch events

### 4. Form Submission
- Forms read from instance variables (persist after cleanup)
- Fall back to cookies
- Fall back to localStorage
- Backend reads from form fields, then page_url, then cookies

## Key Components

### UTMTracker Class

**File:** `v2/js/utm-tracking.js`

**Methods:**
- `setupUTMCleanup()` - Sets up cleanup with feature flag check
- `waitForAnalyticsReady()` - Waits for analytics scripts
- `cleanUTMParametersFromURL()` - Removes UTMs from URL
- `preventInternalUTMCarryover()` - Removes UTMs from internal links

### Feature Flag

**File:** `v2/js/utm-cleanup-feature-flag.js`

**Purpose:**
- Allows A/B testing
- Quick rollback capability
- Testing without code changes

**Usage:**
```javascript
localStorage.setItem('utmCleanupEnabled', 'false'); // Disable
localStorage.setItem('utmCleanupEnabled', 'true');  // Enable
```

### Form Integration

**File:** `v2/base/include_form-hs.php`

**Methods:**
- `populateUTMFields()` - Populates form fields from tracker
- Uses `window.utmTracker.getUTMDataForAPI()`
- Falls back to cookies/localStorage

### Backend Processing

**File:** `html/form-hs.php`

**Logic:**
- Reads UTMs from form fields first
- Falls back to page_url
- Falls back to cookies
- Extracts hsa_* from page_url or cookies

## Event System

### Events Dispatched

1. **utmCleanupComplete**
   - Fired when cleanup succeeds
   - Contains: timestamp, url, hadUTMs, hadTracking, duration, success

2. **utmCleanupError**
   - Fired when cleanup fails
   - Contains: timestamp, error, errorName

### DataLayer Events

1. **utm_cleanup_complete**
   - Sent to dataLayer for analytics
   - Contains: cleanup_success, cleanup_duration, had_utms, had_tracking

2. **utm_cleanup_error**
   - Sent to dataLayer for monitoring
   - Contains: cleanup_success (false), error

## Monitoring Integration

### GTM Setup

1. **Create Triggers:**
   - `utm_cleanup_complete` event
   - `utm_cleanup_error` event

2. **Create Tags:**
   - GA4 event tag for cleanup complete
   - GA4 event tag for cleanup error

3. **Create Alerts:**
   - Error rate > 10%
   - Success rate < 90%

### Metrics to Track

- Cleanup success rate
- Cleanup duration
- Analytics capture timing
- Form attribution accuracy
- Error rate

## Error Handling

### Graceful Degradation

- If cleanup fails, UTMs remain in URL (no data loss)
- Forms still work (use cookies/localStorage)
- Analytics still capture (UTMs in URL)
- Page continues to function

### Error Tracking

- Errors logged to console (debug mode)
- Errors sent to dataLayer
- Errors dispatched as events
- Errors tracked in analytics

## Performance Considerations

### Overhead

- Cleanup setup: ~5ms
- Cleanup execution: ~2ms
- Monitoring: ~5ms
- **Total:** ~12ms (negligible)

### Optimization

- Non-blocking execution
- Efficient URL manipulation
- Minimal DOM operations
- Cache-friendly

## Browser Compatibility

### Supported

- Chrome/Edge (Chromium) ✅
- Firefox ✅
- Safari ✅
- Mobile browsers ✅

### Fallbacks

- Feature detection before use
- Graceful degradation
- Error handling
- Fallback to keeping UTMs

## Security Considerations

### Same-Origin Policy

- `history.replaceState()` respects same-origin
- May fail on cross-origin (graceful failure)
- Errors caught and handled

### Privacy

- UTMs removed from visible URL
- Less tracking data exposed
- Privacy-friendly

## Related Documentation

- `docs/development/UTM_CLEANUP_IMPROVEMENTS.md` - Improvements
- `docs/development/UTM_CLEANUP_BEST_PRACTICES.md` - Best practices
- [`UTM_CLEANUP_FINAL_RECOMMENDATION.md`](../archive/2026-04-01-docs-cleanup/utm-cleanup-analysis/UTM_CLEANUP_FINAL_RECOMMENDATION.md) — Recommendation (archived analysis)
