Major refactoring of ourdigital-custom-skills with new numbering system: ## Structure Changes - Each skill now has code/ (Claude Code) and desktop/ (Claude Desktop) versions - New progressive numbering: 01-09 General, 10-19 SEO, 20-29 GTM, 30-39 OurDigital, 40-49 Jamie ## Skill Reorganization - 01-notion-organizer (from 02) - 10-18: SEO tools split into focused skills (technical, on-page, local, schema, vitals, gsc, gateway) - 20-21: GTM audit and manager - 30-32: OurDigital designer, research, presentation - 40-41: Jamie brand editor and audit ## New Files - .claude/commands/: Slash command definitions for all skills - CLAUDE.md: Updated with new skill structure documentation - REFACTORING_PLAN.md: Migration documentation - COMPATIBILITY_REPORT.md, SKILLS_COMPARISON.md: Analysis docs ## Removed - Old skill directories (02-05, 10-14, 20-21 old numbering) - Consolidated into new structure with _archive/ for reference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
Form Tracking Reference
GA4 Form Events
form_start
Fires on first interaction with form field.
dataLayer.push({
event: "form_start",
form_id: "contact-form",
form_name: "Contact Us",
form_destination: "/submit-contact"
});
form_submit
Fires on successful form submission.
dataLayer.push({
event: "form_submit",
form_id: "contact-form",
form_name: "Contact Us",
form_destination: "/submit-contact",
form_submit_text: "Send Message"
});
generate_lead
Fires when form generates a qualified lead.
dataLayer.push({
event: "generate_lead",
currency: "USD",
value: 100, // Estimated lead value
form_id: "quote-request"
});
Form Field Events (Custom)
field_focus
dataLayer.push({
event: "field_focus",
form_id: "signup-form",
field_name: "email",
field_type: "email"
});
field_complete
dataLayer.push({
event: "field_complete",
form_id: "signup-form",
field_name: "email",
field_type: "email",
is_valid: true
});
field_error
dataLayer.push({
event: "field_error",
form_id: "signup-form",
field_name: "email",
error_message: "Invalid email format"
});
Form Abandonment Tracking
Detecting Abandonment
Track when user leaves form without submitting:
// Track form start
let formStarted = false;
document.querySelectorAll('form input, form select, form textarea')
.forEach(field => {
field.addEventListener('focus', function() {
if (!formStarted) {
formStarted = true;
dataLayer.push({ event: 'form_start', form_id: this.form.id });
}
});
});
// Track abandonment on page leave
window.addEventListener('beforeunload', function() {
if (formStarted && !formSubmitted) {
dataLayer.push({
event: 'form_abandon',
form_id: 'contact-form',
last_field: lastFocusedField,
fields_completed: completedFieldCount
});
}
});
GTM Trigger Configuration
Form Submission Trigger
| Setting | Value |
|---|---|
| Trigger Type | Form Submission |
| Wait for Tags | Check (if AJAX form) |
| Check Validation | Check |
| Form ID | equals contact-form |
Form Start Trigger (Custom Event)
| Setting | Value |
|---|---|
| Trigger Type | Custom Event |
| Event Name | form_start |
| Fire On | All Custom Events |
Common Form Types & Tracking
Contact Forms
Events: form_start, form_submit, generate_lead
Newsletter Signup
Events: form_start, form_submit, sign_up
Login Forms
Events: form_start, login
Search Forms
Events: search (with search_term parameter)
Multi-Step Forms
Track each step:
dataLayer.push({
event: "form_step",
form_id: "checkout-form",
step_number: 2,
step_name: "Shipping Address"
});
Validation Checklist
- Form has id or name attribute
- All required fields have names
- Submit button identifiable
- form_start fires on first interaction
- form_submit fires only on success
- generate_lead has value parameter
- Error events track validation failures
- Abandonment tracking implemented (optional)