# Form Tracking Troubleshooting Guide

**Last Updated:** 2025-11-28

Common issues and solutions for GTM form tracking implementation.

## Quick Diagnosis

### Check DataLayer

Open browser console and check dataLayer:

```javascript
// View all dataLayer events
console.log(window.dataLayer);

// Filter form submission events
window.dataLayer.filter((e) => e.event === "form_submit");
```

### Check GTM Preview Mode

1. Open GTM Preview mode
2. Navigate to page with form
3. Submit form
4. Check:
   - **Tags Fired:** Should show GA4 event tag
   - **DataLayer:** Should show `form_submit` event
   - **Variables:** Should show populated values

### Check Browser Console

Look for errors or debug messages:

```javascript
// Debug messages (only on localhost)
[GTM Form Tracker] Form submission tracked: {...}

// Errors
[GTM Form Tracker] Error pushing to dataLayer: {...}
```

## Common Issues

### Issue 1: Trigger Not Firing

**Symptoms:**

- Form submits but no GTM trigger fires
- No GA4 event received

**Possible Causes:**

1. Form submits via JavaScript (not standard form submission)
2. Form ID doesn't match trigger condition
3. Page URL condition too restrictive
4. Form is in iframe (GTM can't detect)

**Solutions:**

**For JavaScript-based submissions:**

- Use Custom Event trigger instead of Form Submission trigger
- Ensure dataLayer push happens before form submission

**For form ID mismatch:**

- Check actual form ID in browser DevTools
- Update trigger condition to match actual form ID
- Use Form Element variable instead of Form ID if form has no ID

**For page URL condition:**

- Remove or relax page URL condition
- Use Page Path variable instead of Page URL

**For iframe forms:**

- Implement postMessage communication
- Track in parent window if possible

### Issue 2: DataLayer Variables Not Populating

**Symptoms:**

- Trigger fires but variables are empty
- GA4 event received but parameters missing

**Possible Causes:**

1. Variable name mismatch (case-sensitive)
2. DataLayer push happens after trigger fires
3. Variable not enabled in GTM

**Solutions:**

**Check variable names:**

- Verify dataLayer variable names match exactly
- Check case sensitivity (`form_id` vs `formId`)
- Review dataLayer tab in GTM Preview to see actual push

**Check timing:**

- Ensure dataLayer push happens before form submission
- Use GTM Preview mode to verify push timing
- Check if form submission redirects immediately (may prevent push)

**Enable variables:**

- Go to Variables → User-Defined Variables
- Ensure all required variables are enabled
- Check variable configuration (Data Layer Variable Name)

### Issue 3: Duplicate Events

**Symptoms:**

- Same form submission tracked multiple times
- Multiple GA4 events for single submission

**Possible Causes:**

1. Multiple triggers firing for same form
2. DataLayer push happens multiple times
3. Both universal and specific triggers active

**Solutions:**

**Review triggers:**

- Check if both universal and specific triggers fire
- Use trigger priority or conditions to prevent duplicates
- Disable universal trigger if specific triggers cover all cases

**Check JavaScript:**

- Verify tracking call happens only once
- Check for duplicate event listeners
- Review form submission flow for multiple tracking calls

**Use trigger conditions:**

- Add conditions to prevent multiple triggers firing
- Example: Use form ID condition on universal trigger to exclude specific forms

### Issue 4: HubSpot Embedded Forms Not Tracking

**Symptoms:**

- HubSpot embedded form submits but no tracking
- No dataLayer push for HubSpot forms

**Possible Causes:**

1. `onFormSubmit` callback not implemented
2. GTMFormTracker not loaded when callback fires
3. Form ID incorrect in tracking call

**Solutions:**

**Check callbacks:**

- Verify `onFormSubmit` and `onFormSubmitted` callbacks are implemented
- Check if callbacks fire (add console.log for debugging)
- Ensure callbacks are in `hbspt.forms.create()` configuration

**Check script loading:**

- Verify `gtm-form-tracking.js` loads before HubSpot forms script
- Check script loading order in `head.php`
- Ensure script loads with `defer` (not `async`)

**Verify form ID:**

- Check form ID in HubSpot dashboard
- Verify form ID matches in tracking call
- Use correct portal ID and region

### Issue 5: API-Based Forms Not Tracking

**Symptoms:**

- API form submits but no tracking
- No dataLayer push before API call

**Possible Causes:**

1. Tracking call missing before fetch/XMLHttpRequest
2. Tracking call in wrong location
3. Form submission happens too quickly

**Solutions:**

**Add tracking before API call:**

```javascript
// ✅ CORRECT - Track before fetch
if (window.GTMFormTracker) {
    window.GTMFormTracker.trackAPIForm('endpoint.php', options);
}
const response = await fetch('/v2/api/endpoint.php', {...});
```

**Check call location:**

- Ensure tracking happens in form submit handler
- Verify tracking happens before any async operations
- Check if form validation prevents tracking call

**Handle async forms:**

- For async forms, track immediately when user submits
- Don't wait for validation or other async operations

### Issue 6: Missing UTM Data

**Symptoms:**

- Form tracking works but UTM parameters are empty
- No attribution data in GA4

**Possible Causes:**

1. UTM tracker not loaded
2. UTM data not available when tracking fires
3. UTM parameters not in URL

**Solutions:**

**Check UTM tracker:**

- Verify `utm-tracking.js` loads before `gtm-form-tracking.js`
- Check if `window.utmTracker` exists
- Review UTM tracker initialization

**Check UTM data:**

- Verify UTM parameters in URL
- Check if UTM data persists in cookies/localStorage
- Review UTM tracker fallback logic

**Timing:**

- UTM data should be available on page load
- If tracking fires before UTM tracker initializes, add delay or check

### Issue 7: Consent Mode Blocking Tracking

**Symptoms:**

- Tracking works in some browsers but not others
- No events in privacy-focused browsers

**Possible Causes:**

1. Consent not granted
2. Consent mode configuration incorrect
3. Browser blocking tracking

**Solutions:**

**Check consent:**

- Verify consent is granted before tracking
- Check consent mode configuration in GTM
- Review consent management platform integration

**Browser limitations:**

- Some browsers (Safari ITP, Firefox ETP) may block tracking
- Document limitation - not a bug
- Consider server-side tracking for critical forms

### Issue 8: Performance Impact

**Symptoms:**

- Page load time increased
- Form submission feels slow

**Possible Causes:**

1. Tracking script blocking
2. Large dataLayer payload
3. Multiple tracking calls

**Solutions:**

**Script loading:**

- Ensure tracking script uses `defer` attribute
- Don't use `async` (may cause timing issues)
- Load script in `<head>` with `defer`

**Minimize payload:**

- Only include necessary data in dataLayer
- Remove unnecessary fields
- Use short variable names

**Optimize calls:**

- Ensure tracking happens once per submission
- Don't add delays for tracking
- Track immediately before submission

## Debugging Techniques

### 1. Browser Console

**Check dataLayer:**

```javascript
// View all events
console.log(window.dataLayer);

// Filter form events
window.dataLayer.filter((e) => e.event === "form_submit");

// Check last event
console.log(window.dataLayer[window.dataLayer.length - 1]);
```

**Check GTMFormTracker:**

```javascript
// Verify utility loaded
console.log(typeof window.GTMFormTracker);

// Check utility methods
console.log(Object.keys(window.GTMFormTracker));
```

### 2. GTM Preview Mode

**Steps:**

1. Open GTM Preview mode
2. Enter preview URL
3. Navigate to page with form
4. Submit form
5. Check:
   - **Summary:** Should show trigger fired
   - **Tags Fired:** Should show GA4 event tag
   - **DataLayer:** Should show `form_submit` event
   - **Variables:** Should show populated values

**What to look for:**

- Trigger fires (green checkmark)
- Variables populate (not empty)
- Tag fires (GA4 event sent)
- No errors in console

### 3. Network Tab

**Check API calls:**

1. Open browser DevTools → Network tab
2. Filter by "collect" or "submit"
3. Submit form
4. Check:
   - API call made (status 200)
   - Request timing (should be after dataLayer push)
   - Request payload (verify data sent)

### 4. GA4 Real-Time Reports

**Steps:**

1. Open GA4 → Reports → Realtime
2. Submit test form
3. Check Events section
4. Look for `form_submit` event
5. Click event to see parameters

**What to verify:**

- Event appears within 30 seconds
- Event parameters populated
- Event count matches submissions (no duplicates)

## Testing Checklist

### Pre-Deployment Testing

- [ ] All forms tested in GTM Preview mode
- [ ] DataLayer pushes verified in browser console
- [ ] Triggers fire correctly
- [ ] Variables populate correctly
- [ ] GA4 events received
- [ ] No duplicate events
- [ ] No console errors
- [ ] Tested on Chrome
- [ ] Tested on Firefox
- [ ] Tested on Safari
- [ ] Tested on mobile devices

### Post-Deployment Testing

- [ ] Verify events in GA4 real-time reports
- [ ] Check for errors in browser console (production)
- [ ] Monitor form submission rates (should match before/after)
- [ ] Verify no performance degradation
- [ ] Check GTM container status (no errors)

## Getting Help

### Before Asking for Help

1. **Check this guide** - Most common issues are covered
2. **Check browser console** - Look for errors or debug messages
3. **Use GTM Preview mode** - Verify trigger/tag behavior
4. **Check dataLayer** - Verify push happens and data is correct
5. **Review code** - Ensure tracking call is in correct location

### Information to Provide

When reporting issues, include:

1. **Form details:**

   - Form ID
   - Form type (custom HTML, HubSpot embedded, API-based)
   - Page URL

2. **Symptoms:**

   - What happens (trigger doesn't fire, variables empty, etc.)
   - When it happens (always, sometimes, specific browsers)

3. **Debugging results:**

   - Browser console output
   - GTM Preview mode results
   - dataLayer contents
   - Network tab results

4. **Environment:**
   - Browser and version
   - Device type (desktop/mobile)
   - Ad blockers installed
   - Privacy settings

## Prevention

### Code Review Checklist

Before deploying form tracking changes:

- [ ] Tracking call added before form submission
- [ ] Form name is descriptive and unique
- [ ] HubSpot form GUID included (if applicable)
- [ ] Error handling in place (utility check)
- [ ] No sensitive data in dataLayer
- [ ] Tested in GTM Preview mode
- [ ] Documentation updated

### Regular Monitoring

- **Weekly:** Check GA4 for form submission events
- **Monthly:** Review GTM container for errors
- **Quarterly:** Full form tracking audit

## Reference

- **Implementation Guide:** `docs/forms/GTM_FORM_TRACKING_GUIDE.md`
- **Developer Guide:** `docs/forms/FORM_TRACKING_DEVELOPER_GUIDE.md`
- **Best Practices:** `docs/forms/FORM_TRACKING_BEST_PRACTICES.md`
