GA4 Event Tracking on Strikingly | OpsBlu Docs

GA4 Event Tracking on Strikingly

Implement custom event tracking for Strikingly sites including form submissions, button clicks, and section engagement.

Beyond basic page views, track user interactions on your Strikingly site with custom GA4 events. This guide covers Strikingly-specific event implementation.

Prerequisite: Complete GA4 Setup before implementing custom events.

Event Tracking Methods

Method Difficulty Use Case
Enhanced Measurement Easy Automatic scrolls, clicks, video
Direct gtag Events Medium Custom button/form tracking
GTM Events Medium-Hard Complex multi-tag tracking

Enhanced Measurement (Automatic Events)

Enable in GA4 for automatic tracking without additional code.

Enable Enhanced Measurement

  1. Go to GA4 AdminData Streams
  2. Click your web stream
  3. Enable Enhanced measurement
  4. Configure which events to track:

Available Events:

  • Page views - Automatic
  • Scrolls - When user scrolls 90%
  • Outbound clicks - Clicks to external sites
  • Site search - If you have search functionality
  • Video engagement - YouTube/Vimeo plays
  • File downloads - PDF, DOC, etc.

Customize Enhanced Measurement

// Modify scroll threshold
gtag('config', 'G-XXXXXXXXXX', {
  'send_page_view': true,
  'scroll_threshold': 75 // Track at 75% instead of 90%
});

Tracking Strikingly Sections

One-page Strikingly sites need custom section tracking.

Section Visibility Tracking

Track when users view different sections:

// Add to Header Code (after GA4 initialization)
document.addEventListener('DOMContentLoaded', function() {
  const sections = document.querySelectorAll('section');
  const trackedSections = new Set();

  const observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
      if (entry.isIntersecting) {
        const sectionId = entry.target.id || 'section-' + entry.target.dataset.index;

        // Only track each section once per session
        if (!trackedSections.has(sectionId)) {
          trackedSections.add(sectionId);

          gtag('event', 'section_view', {
            'section_id': sectionId,
            'section_name': getSectionName(entry.target)
          });
        }
      }
    });
  }, { threshold: 0.5 }); // 50% visibility triggers event

  sections.forEach(function(section, index) {
    section.dataset.index = index;
    observer.observe(section);
  });

  function getSectionName(element) {
    // Try to get a readable name
    const heading = element.querySelector('h1, h2, h3');
    if (heading) return heading.textContent.trim();

    return element.id || 'Section ' + (parseInt(element.dataset.index) + 1);
  }
});

Virtual Page Views for Sections

Alternative approach using virtual page views:

document.addEventListener('DOMContentLoaded', function() {
  const sections = document.querySelectorAll('section[data-page-title]');
  const viewedSections = new Set();

  const observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
      if (entry.isIntersecting) {
        const sectionId = entry.target.id;
        const pageTitle = entry.target.getAttribute('data-page-title');

        if (!viewedSections.has(sectionId)) {
          viewedSections.add(sectionId);

          // Send virtual page view
          gtag('event', 'page_view', {
            'page_title': pageTitle,
            'page_location': window.location.href + '#' + sectionId,
            'page_path': '/' + sectionId
          });
        }
      }
    });
  }, { threshold: 0.6 });

  sections.forEach(function(section) {
    observer.observe(section);
  });
});

HTML Requirement: Add data-page-title to sections in custom HTML:

<section id="about" data-page-title="About Us">
  <!-- Section content -->
</section>

Form Submission Tracking

Track Strikingly contact forms and newsletter signups.

Contact Form Tracking

document.addEventListener('DOMContentLoaded', function() {
  // Strikingly forms typically have class 's-contact-form'
  const forms = document.querySelectorAll('.s-contact-form, form');

  forms.forEach(function(form, index) {
    form.addEventListener('submit', function(e) {
      // Get form identifier
      const formName = form.getAttribute('name') ||
                      form.id ||
                      'form-' + index;

      gtag('event', 'form_submit', {
        'form_name': formName,
        'form_type': 'contact'
      });

      // Optional: Track form fields submitted
      const formData = new FormData(form);
      const fields = [];
      formData.forEach(function(value, key) {
        fields.push(key);
      });

      gtag('event', 'form_submit', {
        'form_name': formName,
        'fields_submitted': fields.join(',')
      });
    });
  });
});

Newsletter Signup Tracking

document.addEventListener('DOMContentLoaded', function() {
  const newsletterForms = document.querySelectorAll('.s-email-form');

  newsletterForms.forEach(function(form) {
    form.addEventListener('submit', function(e) {
      gtag('event', 'newsletter_signup', {
        'method': 'website_form',
        'location': getFormLocation(form)
      });
    });
  });

  function getFormLocation(element) {
    // Determine which section contains the form
    const section = element.closest('section');
    return section ? (section.id || 'unknown') : 'footer';
  }
});

Form Success/Error Tracking

Track form submission outcomes:

// Monitor for Strikingly's success message
const observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    mutation.addedNodes.forEach(function(node) {
      if (node.classList && node.classList.contains('s-form-success')) {
        gtag('event', 'form_success', {
          'event_category': 'form',
          'event_label': 'contact_form'
        });
      }
      if (node.classList && node.classList.contains('s-form-error')) {
        gtag('event', 'form_error', {
          'event_category': 'form',
          'event_label': 'contact_form'
        });
      }
    });
  });
});

observer.observe(document.body, {
  childList: true,
  subtree: true
});

Button Click Tracking

Track CTA buttons and important interactions.

Generic Button Tracking

document.addEventListener('DOMContentLoaded', function() {
  // Track all buttons with data-event attribute
  document.addEventListener('click', function(e) {
    const button = e.target.closest('[data-event]');

    if (button) {
      const eventName = button.getAttribute('data-event');
      const eventLabel = button.getAttribute('data-label') ||
                        button.textContent.trim();

      gtag('event', eventName, {
        'event_category': 'button',
        'event_label': eventLabel,
        'button_text': button.textContent.trim()
      });
    }
  });
});

HTML Usage: Add to custom HTML buttons:

<button data-event="cta_click" data-label="Get Started">
  Get Started
</button>

Specific CTA Tracking

document.addEventListener('DOMContentLoaded', function() {
  // Track primary CTA buttons
  const ctaButtons = document.querySelectorAll('.s-cta-button, .s-button');

  ctaButtons.forEach(function(button) {
    button.addEventListener('click', function() {
      gtag('event', 'cta_click', {
        'event_category': 'engagement',
        'event_label': button.textContent.trim(),
        'cta_location': getElementLocation(button)
      });
    });
  });

  function getElementLocation(element) {
    const section = element.closest('section');
    if (section) {
      return section.id || section.querySelector('h1, h2, h3')?.textContent || 'unknown';
    }
    return 'unknown';
  }
});
document.addEventListener('click', function(e) {
  const link = e.target.closest('a');

  if (link && link.href) {
    const href = link.href;
    const fileExtensions = /\.(pdf|doc|docx|xls|xlsx|zip|rar|txt|csv)$/i;

    if (fileExtensions.test(href)) {
      const fileName = href.split('/').pop();

      gtag('event', 'file_download', {
        'event_category': 'download',
        'event_label': fileName,
        'file_type': href.split('.').pop().toLowerCase()
      });
    }
  }
});

Social Media Click Tracking

Track social media link clicks.

document.addEventListener('DOMContentLoaded', function() {
  const socialLinks = document.querySelectorAll('.s-social-icon a, a[href*="facebook.com"], a[href*="twitter.com"], a[href*="instagram.com"], a[href*="linkedin.com"]');

  socialLinks.forEach(function(link) {
    link.addEventListener('click', function() {
      const platform = getSocialPlatform(link.href);

      gtag('event', 'social_click', {
        'event_category': 'social',
        'event_label': platform,
        'link_url': link.href
      });
    });
  });

  function getSocialPlatform(url) {
    if (url.includes('facebook.com')) return 'Facebook';
    if (url.includes('twitter.com') || url.includes('x.com')) return 'Twitter';
    if (url.includes('instagram.com')) return 'Instagram';
    if (url.includes('linkedin.com')) return 'LinkedIn';
    if (url.includes('youtube.com')) return 'YouTube';
    return 'Other';
  }
});

Strikingly E-commerce Events

Track Strikingly Simple Store interactions.

Product View Events

document.addEventListener('DOMContentLoaded', function() {
  const productItems = document.querySelectorAll('.s-ecommerce-item');

  productItems.forEach(function(item) {
    item.addEventListener('click', function() {
      const productName = item.querySelector('.product-name')?.textContent || 'Unknown';
      const productPrice = item.querySelector('.product-price')?.textContent || '0';

      gtag('event', 'view_item', {
        'currency': 'USD',
        'value': parsePrice(productPrice),
        'items': [{
          'item_id': item.dataset.productId || 'unknown',
          'item_name': productName,
          'price': parsePrice(productPrice)
        }]
      });
    });
  });

  function parsePrice(priceString) {
    return parseFloat(priceString.replace(/[^0-9.]/g, '')) || 0;
  }
});

Add to Cart Event

document.addEventListener('click', function(e) {
  const addToCartBtn = e.target.closest('.s-ecommerce-add-to-cart, .add-to-cart-button');

  if (addToCartBtn) {
    const productContainer = addToCartBtn.closest('.s-ecommerce-item');
    const productName = productContainer?.querySelector('.product-name')?.textContent || 'Unknown';
    const productPrice = productContainer?.querySelector('.product-price')?.textContent || '0';

    gtag('event', 'add_to_cart', {
      'currency': 'USD',
      'value': parsePrice(productPrice),
      'items': [{
        'item_name': productName,
        'price': parsePrice(productPrice),
        'quantity': 1
      }]
    });
  }

  function parsePrice(priceString) {
    return parseFloat(priceString.replace(/[^0-9.]/g, '')) || 0;
  }
});

Purchase Event (Thank You Page)

Add to custom code on your thank you/confirmation page:

// Only fire on order confirmation page
if (window.location.pathname.includes('/store/order/') ||
    window.location.search.includes('order_id=')) {

  gtag('event', 'purchase', {
    'transaction_id': getOrderId(),
    'value': getTotalValue(),
    'currency': 'USD',
    'tax': 0,
    'shipping': 0,
    'items': getOrderItems()
  });
}

function getOrderId() {
  // Extract from URL or page content
  const urlParams = new URLSearchParams(window.location.search);
  return urlParams.get('order_id') || 'unknown';
}

function getTotalValue() {
  // Extract from page content
  const totalElement = document.querySelector('.order-total, .total-price');
  if (totalElement) {
    return parseFloat(totalElement.textContent.replace(/[^0-9.]/g, '')) || 0;
  }
  return 0;
}

function getOrderItems() {
  // Extract items from order summary
  const items = [];
  const orderItems = document.querySelectorAll('.order-item');

  orderItems.forEach(function(item) {
    items.push({
      'item_name': item.querySelector('.item-name')?.textContent || 'Unknown',
      'price': parseFloat(item.querySelector('.item-price')?.textContent.replace(/[^0-9.]/g, '')) || 0,
      'quantity': parseInt(item.querySelector('.item-quantity')?.textContent) || 1
    });
  });

  return items;
}

Video Engagement Tracking

Track video plays (YouTube/Vimeo embedded).

YouTube Video Tracking

// Track YouTube embeds
document.addEventListener('DOMContentLoaded', function() {
  const youtubeIframes = document.querySelectorAll('iframe[src*="youtube.com"]');

  youtubeIframes.forEach(function(iframe) {
    iframe.addEventListener('load', function() {
      // YouTube Player API tracking
      const player = new YT.Player(iframe);

      player.addEventListener('onStateChange', function(event) {
        const videoTitle = iframe.title || 'Unknown Video';

        if (event.data === YT.PlayerState.PLAYING) {
          gtag('event', 'video_start', {
            'event_category': 'video',
            'event_label': videoTitle,
            'video_provider': 'YouTube'
          });
        }

        if (event.data === YT.PlayerState.ENDED) {
          gtag('event', 'video_complete', {
            'event_category': 'video',
            'event_label': videoTitle,
            'video_provider': 'YouTube'
          });
        }
      });
    });
  });
});

Note: Requires YouTube IFrame API. Enhanced Measurement tracks this automatically if enabled.

Scroll Depth Tracking

More granular scroll tracking than Enhanced Measurement:

document.addEventListener('DOMContentLoaded', function() {
  const scrollThresholds = [25, 50, 75, 100];
  const triggeredThresholds = new Set();

  window.addEventListener('scroll', function() {
    const scrollPercentage = (window.scrollY + window.innerHeight) / document.body.scrollHeight * 100;

    scrollThresholds.forEach(function(threshold) {
      if (scrollPercentage >= threshold && !triggeredThresholds.has(threshold)) {
        triggeredThresholds.add(threshold);

        gtag('event', 'scroll', {
          'event_category': 'engagement',
          'event_label': threshold + '%',
          'percent_scrolled': threshold
        });
      }
    });
  });
});

Time on Site Tracking

Track engaged time on site:

let startTime = Date.now();
let isActive = true;
let lastActivityTime = Date.now();

// Track active time
document.addEventListener('visibilitychange', function() {
  if (document.hidden) {
    isActive = false;
    sendTimeEngaged();
  } else {
    isActive = true;
    lastActivityTime = Date.now();
  }
});

// Reset activity timer on user interaction
['mousedown', 'keydown', 'scroll', 'touchstart'].forEach(function(event) {
  document.addEventListener(event, function() {
    lastActivityTime = Date.now();
  });
});

// Send engaged time every 30 seconds
setInterval(function() {
  if (isActive && (Date.now() - lastActivityTime < 5000)) {
    sendTimeEngaged();
  }
}, 30000);

function sendTimeEngaged() {
  const timeEngaged = Math.round((Date.now() - startTime) / 1000);

  gtag('event', 'time_engaged', {
    'event_category': 'engagement',
    'event_label': Math.floor(timeEngaged / 60) + ' minutes',
    'value': timeEngaged
  });
}

// Send on page unload
window.addEventListener('beforeunload', sendTimeEngaged);

Testing and Debugging

Test Events in GA4 DebugView

  1. Enable debug mode:
gtag('config', 'G-XXXXXXXXXX', {
  'debug_mode': true
});
  1. Visit your site and trigger events
  2. Check AdminDebugView in GA4
  3. Verify events appear with correct parameters

Console Logging for Development

// Add to Header Code for debugging
const originalGtag = gtag;
window.gtag = function() {
  console.log('GA4 Event:', arguments);
  originalGtag.apply(this, arguments);
};

Browser Console Testing

Test events directly in console:

// Test an event
gtag('event', 'test_event', {
  'event_category': 'test',
  'event_label': 'manual test'
});

Best Practices

Event Naming

  • Use lowercase with underscores: section_view, cta_click
  • Be descriptive but concise
  • Follow GA4 recommended events when possible
  • Consistent naming across similar events

Event Parameters

  • Include relevant context (section, location, value)
  • Keep parameter names consistent
  • Don't send PII (personally identifiable information)
  • Limit to 25 custom parameters per event

Performance

  • Don't track every micro-interaction
  • Use debouncing for scroll/resize events
  • Batch similar events when possible
  • Test impact on page load time

Data Quality

  • Test all events thoroughly before launch
  • Monitor in GA4 for duplicate events
  • Validate event parameters are correct
  • Document all custom events

Complete Event Tracking Code

Comprehensive starter template for Strikingly sites:

// Add to Header Code (after GA4 initialization)
(function() {
  'use strict';

  // Wait for DOM
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }

  function init() {
    trackSections();
    trackForms();
    trackButtons();
    trackSocialLinks();
    trackScrollDepth();
  }

  // Section visibility tracking
  function trackSections() {
    const sections = document.querySelectorAll('section');
    const tracked = new Set();
    const observer = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting && !tracked.has(entry.target)) {
          tracked.add(entry.target);
          gtag('event', 'section_view', {
            'section_id': entry.target.id || 'section-' + tracked.size
          });
        }
      });
    }, { threshold: 0.5 });

    sections.forEach(function(s) { observer.observe(s); });
  }

  // Form submission tracking
  function trackForms() {
    const forms = document.querySelectorAll('form');
    forms.forEach(function(form, i) {
      form.addEventListener('submit', function() {
        gtag('event', 'form_submit', {
          'form_name': form.name || form.id || 'form-' + i
        });
      });
    });
  }

  // Button click tracking
  function trackButtons() {
    document.addEventListener('click', function(e) {
      const btn = e.target.closest('button, .s-cta-button, [data-event]');
      if (btn) {
        gtag('event', btn.dataset.event || 'button_click', {
          'event_label': btn.textContent.trim()
        });
      }
    });
  }

  // Social link tracking
  function trackSocialLinks() {
    const social = document.querySelectorAll('a[href*="facebook.com"], a[href*="twitter.com"], a[href*="instagram.com"], a[href*="linkedin.com"]');
    social.forEach(function(link) {
      link.addEventListener('click', function() {
        gtag('event', 'social_click', {
          'event_label': link.href.match(/\/\/(.*?)\./)[1]
        });
      });
    });
  }

  // Scroll depth tracking
  function trackScrollDepth() {
    const depths = [25, 50, 75, 100];
    const reached = new Set();
    window.addEventListener('scroll', function() {
      const pct = (window.scrollY + window.innerHeight) / document.body.scrollHeight * 100;
      depths.forEach(function(d) {
        if (pct >= d && !reached.has(d)) {
          reached.add(d);
          gtag('event', 'scroll', {
            'percent_scrolled': d
          });
        }
      });
    });
  }
})();

Next Steps

For general event tracking concepts, see Google Analytics Event Tracking.