Learn how to track Weebly-specific events in Google Analytics 4, including form submissions, button clicks, ecommerce events (via Square), and custom user interactions.
Prerequisites
Before implementing event tracking:
- GA4 installed on Weebly
- Weebly paid plan (Personal, Professional, or Performance for code access)
- Access to Weebly's Header/Footer Code sections
- Basic understanding of JavaScript (for custom events)
Implementation Methods
| Method | Best For | Customization | Plan Required |
|---|---|---|---|
| Enhanced Measurement | Quick setup, standard events | Low - automatic | Any with GA4 |
| Manual gtag.js Events | Custom tracking needs | Medium - code required | Personal+ |
| Google Tag Manager | Complex tracking, multiple events | High - visual interface | Personal+ |
Enhanced Measurement (Automatic Events)
GA4's Enhanced Measurement tracks common interactions automatically. No Weebly code changes required!
Enable Enhanced Measurement
- In GA4, go to Admin → Data Streams
- Click your Web stream
- Toggle Enhanced Measurement ON
- Configure which events to track:
- ✓ Page views (always on)
- ✓ Scrolls (90% depth)
- ✓ Outbound clicks
- ✓ Site search
- ✓ Video engagement (YouTube, Vimeo)
- ✓ File downloads (PDF, DOC, etc.)
Events Tracked Automatically
page_view - Every page load including Weebly blog posts
scroll - User scrolls 90% of page depth
click - Outbound link clicks (links to external domains)
file_download - Downloads of: pdf, doc, docx, txt, rtf, csv, xls, xlsx, ppt, pptx, zip
video_start, video_progress, video_complete - Embedded YouTube/Vimeo videos
view_search_results - Weebly search results (if search enabled)
Custom Event Tracking on Weebly
Track Weebly-specific interactions with custom events using Header/Footer Code.
Access Weebly Code Injection
- In Weebly editor, click Settings → SEO
- Scroll to Header Code and Footer Code sections
- Add tracking code to appropriate section:
- Header Code: For tracking that needs to load early
- Footer Code: For tracking that can load after page content (recommended for performance)
Form Submissions
Track Weebly contact forms and lead forms.
Method 1: Generic Form Tracking
Add to Weebly's Footer Code section:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Track all Weebly forms
const forms = document.querySelectorAll('form, .wsite-form-container form');
forms.forEach(function(form) {
form.addEventListener('submit', function(e) {
const formName = this.getAttribute('name') ||
this.getAttribute('class') ||
'weebly_contact_form';
// Don't prevent default - let Weebly handle submission
gtag('event', 'form_submission', {
'form_name': formName,
'form_location': window.location.pathname,
'form_type': 'contact_form'
});
});
});
});
</script>
Method 2: Track Specific Weebly Forms
Weebly forms have specific classes you can target:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Track contact form
const contactForm = document.querySelector('.wsite-form-container form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
gtag('event', 'contact_form_submit', {
'form_type': 'contact',
'page_path': window.location.pathname,
'form_fields': this.querySelectorAll('input, textarea').length
});
});
}
// Track newsletter/email signup forms
const emailForms = document.querySelectorAll('.wsite-form-type-email form');
emailForms.forEach(function(form) {
form.addEventListener('submit', function(e) {
gtag('event', 'newsletter_signup', {
'method': 'weebly_form',
'page_path': window.location.pathname
});
});
});
});
</script>
Method 3: Track Form Fields Completed
Track which form fields users interact with:
<script>
document.addEventListener('DOMContentLoaded', function() {
const formInputs = document.querySelectorAll('form input, form textarea, form select');
formInputs.forEach(function(input) {
let interacted = false;
input.addEventListener('blur', function() {
if (!interacted && this.value.trim() !== '') {
interacted = true;
gtag('event', 'form_field_interaction', {
'field_type': this.type || 'textarea',
'field_name': this.name || this.id || 'unknown',
'page_location': window.location.pathname
});
}
});
});
});
</script>
Button Click Tracking
Track important button clicks including CTAs:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Track Weebly button elements
const buttons = document.querySelectorAll('.wsite-button, .wsite-button-normal, .wsite-button-highlight');
buttons.forEach(function(button) {
button.addEventListener('click', function() {
const buttonText = this.textContent.trim();
const buttonClass = this.className;
const isHighlight = buttonClass.includes('highlight');
gtag('event', 'button_click', {
'button_text': buttonText,
'button_location': window.location.pathname,
'button_type': isHighlight ? 'highlight' : 'normal',
'button_url': this.href || 'no_link'
});
});
});
// Track custom CTA buttons (if you've added custom classes)
const ctaButtons = document.querySelectorAll('[data-track="cta"]');
ctaButtons.forEach(function(button) {
button.addEventListener('click', function() {
gtag('event', 'cta_click', {
'cta_text': this.textContent.trim(),
'cta_location': window.location.pathname,
'cta_destination': this.href || ''
});
});
});
});
</script>
Phone Number Clicks (Click-to-Call)
Track when users click phone numbers on Weebly sites:
<script>
document.addEventListener('DOMContentLoaded', function() {
const phoneLinks = document.querySelectorAll('a[href^="tel:"]');
phoneLinks.forEach(function(link) {
link.addEventListener('click', function() {
const phoneNumber = this.getAttribute('href').replace('tel:', '');
gtag('event', 'phone_call', {
'phone_number': phoneNumber,
'page_location': window.location.pathname,
'link_text': this.textContent,
'link_class': this.className
});
});
});
});
</script>
Email Link Clicks
Track mailto link clicks:
<script>
document.addEventListener('DOMContentLoaded', function() {
const emailLinks = document.querySelectorAll('a[href^="mailto:"]');
emailLinks.forEach(function(link) {
link.addEventListener('click', function() {
gtag('event', 'email_click', {
'email_to': this.getAttribute('href').replace('mailto:', '').split('?')[0],
'page_location': window.location.pathname,
'link_text': this.textContent
});
});
});
});
</script>
Social Media Link Tracking
Track social media icon clicks in Weebly:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Weebly social icons have specific classes
const socialLinks = document.querySelectorAll('.wsite-social-item a, a[href*="facebook.com"], a[href*="twitter.com"], a[href*="instagram.com"], a[href*="linkedin.com"], a[href*="youtube.com"]');
socialLinks.forEach(function(link) {
link.addEventListener('click', function() {
let platform = 'unknown';
const href = this.href.toLowerCase();
if (href.includes('facebook.com')) platform = 'facebook';
else if (href.includes('twitter.com') || href.includes('x.com')) platform = 'twitter';
else if (href.includes('instagram.com')) platform = 'instagram';
else if (href.includes('linkedin.com')) platform = 'linkedin';
else if (href.includes('youtube.com')) platform = 'youtube';
else if (href.includes('pinterest.com')) platform = 'pinterest';
else if (href.includes('tiktok.com')) platform = 'tiktok';
gtag('event', 'social_click', {
'social_network': platform,
'link_url': this.href,
'page_location': window.location.pathname,
'link_location': 'weebly_social_icons'
});
});
});
});
</script>
Ecommerce Tracking (Weebly/Square Integration)
Weebly's ecommerce is powered by Square. Tracking ecommerce events requires accessing product data from the page.
Important Note: Weebly doesn't provide a native data layer for ecommerce. Square handles checkout, making comprehensive tracking limited. Consider using Square's analytics for detailed ecommerce data.
View Item (Product Page)
Track product page views by extracting data from the page:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Check if we're on a product page
const productName = document.querySelector('.wsite-com-product-title');
const productPrice = document.querySelector('.wsite-com-product-price');
const productImage = document.querySelector('.wsite-com-product-images img');
if (productName && productPrice) {
const price = parseFloat(productPrice.textContent.replace(/[^0-9.]/g, ''));
const name = productName.textContent.trim();
gtag('event', 'view_item', {
'currency': 'USD', // Change to your currency
'value': price,
'items': [{
'item_name': name,
'price': price,
'quantity': 1
}]
});
}
});
</script>
Add to Cart
Track add to cart button clicks:
<script>
document.addEventListener('DOMContentLoaded', function() {
const addToCartButtons = document.querySelectorAll('.wsite-com-product-add-to-cart');
addToCartButtons.forEach(function(button) {
button.addEventListener('click', function() {
// Get product data from page
const productContainer = this.closest('.wsite-com-product-container');
const productName = productContainer?.querySelector('.wsite-com-product-title')?.textContent?.trim();
const productPrice = productContainer?.querySelector('.wsite-com-product-price')?.textContent;
if (productName && productPrice) {
const price = parseFloat(productPrice.replace(/[^0-9.]/g, ''));
gtag('event', 'add_to_cart', {
'currency': 'USD',
'value': price,
'items': [{
'item_name': productName,
'price': price,
'quantity': 1
}]
});
}
});
});
});
</script>
View Cart
Track when users view their shopping cart:
<script>
// Add to cart page
if (window.location.pathname.includes('/cart') || document.querySelector('.wsite-commerce-cart')) {
gtag('event', 'view_cart', {
'currency': 'USD'
// Note: Cart items are in Square's iframe, so we can't easily access them
});
}
</script>
Begin Checkout
<script>
document.addEventListener('DOMContentLoaded', function() {
const checkoutButton = document.querySelector('.wsite-commerce-checkout-button');
if (checkoutButton) {
checkoutButton.addEventListener('click', function() {
gtag('event', 'begin_checkout', {
'currency': 'USD'
// Cart total is in Square iframe, difficult to access
});
});
}
});
</script>
Square Checkout Limitation: Weebly uses Square for checkout, which happens in an iframe or redirects to Square. You cannot track the final purchase event on Square's domain. Consider:
- Using Square Analytics for purchase data
- Server-side tracking via Square API
- Conversion tracking via thank you page (if available)
Blog Engagement Tracking
Track Weebly blog post interactions:
Blog Post Views
<script>
// Detect if we're on a blog post
if (document.querySelector('.blog-post') || document.querySelector('.wsite-blog-post')) {
const postTitle = document.querySelector('.blog-title, .wsite-blog-title')?.textContent?.trim();
const postCategory = document.querySelector('.blog-category, .wsite-blog-category a')?.textContent?.trim();
gtag('event', 'view_blog_post', {
'blog_title': postTitle || 'Unknown',
'blog_category': postCategory || 'Uncategorized',
'page_location': window.location.pathname
});
}
</script>
Time on Article
Track engaged time on blog posts:
<script>
if (document.querySelector('.blog-post, .wsite-blog-post')) {
let startTime = Date.now();
let engagementSent = false;
window.addEventListener('beforeunload', function() {
const timeSpent = Math.round((Date.now() - startTime) / 1000); // seconds
if (timeSpent > 30 && !engagementSent) {
gtag('event', 'blog_engagement', {
'time_spent_seconds': timeSpent,
'blog_title': document.querySelector('.blog-title')?.textContent?.trim(),
'engaged': timeSpent > 60 ? 'yes' : 'no'
});
engagementSent = true;
}
});
// Also track at 60 second mark
setTimeout(function() {
if (!engagementSent) {
gtag('event', 'blog_engagement', {
'time_spent_seconds': 60,
'blog_title': document.querySelector('.blog-title')?.textContent?.trim(),
'engaged': 'yes'
});
engagementSent = true;
}
}, 60000);
}
</script>
Blog Comments
Track comment submissions on Weebly blog:
<script>
document.addEventListener('DOMContentLoaded', function() {
const commentForm = document.querySelector('.blog-comment-form form, #commentform');
if (commentForm) {
commentForm.addEventListener('submit', function() {
gtag('event', 'blog_comment', {
'blog_title': document.querySelector('.blog-title')?.textContent?.trim(),
'page_location': window.location.pathname
});
});
}
});
</script>
Blog Search
Track blog search usage:
<script>
document.addEventListener('DOMContentLoaded', function() {
const blogSearch = document.querySelector('.blog-search input');
if (blogSearch) {
const blogSearchForm = blogSearch.closest('form');
if (blogSearchForm) {
blogSearchForm.addEventListener('submit', function() {
gtag('event', 'search', {
'search_term': blogSearch.value,
'search_type': 'blog'
});
});
}
}
});
</script>
Video Tracking (Custom Players)
Enhanced Measurement tracks YouTube and Vimeo automatically. For custom HTML5 video:
<script>
document.addEventListener('DOMContentLoaded', function() {
const videos = document.querySelectorAll('video');
videos.forEach(function(video) {
let videoStarted = false;
video.addEventListener('play', function() {
if (!videoStarted) {
videoStarted = true;
gtag('event', 'video_start', {
'video_url': this.currentSrc,
'video_title': this.title || 'Untitled Video',
'page_location': window.location.pathname
});
}
});
video.addEventListener('ended', function() {
gtag('event', 'video_complete', {
'video_url': this.currentSrc,
'video_title': this.title || 'Untitled Video',
'page_location': window.location.pathname
});
});
// Track 50% progress
video.addEventListener('timeupdate', function() {
const progress = (this.currentTime / this.duration) * 100;
if (progress >= 50 && !this.dataset.halfwayTracked) {
this.dataset.halfwayTracked = 'true';
gtag('event', 'video_progress', {
'video_url': this.currentSrc,
'video_title': this.title || 'Untitled Video',
'video_percent': 50
});
}
});
});
});
</script>
Navigation Tracking
Track Weebly menu interactions:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Track main menu clicks
const menuLinks = document.querySelectorAll('.wsite-menu-default a, .wsite-menu a');
menuLinks.forEach(function(link) {
link.addEventListener('click', function() {
gtag('event', 'menu_click', {
'menu_text': this.textContent.trim(),
'menu_url': this.href,
'current_page': window.location.pathname
});
});
});
// Track hamburger menu toggle (mobile)
const hamburger = document.querySelector('.hamburger, .wsite-menu-hamburger');
if (hamburger) {
hamburger.addEventListener('click', function() {
gtag('event', 'mobile_menu_toggle', {
'page_location': window.location.pathname
});
});
}
});
</script>
Membership/Login Tracking
For Weebly sites with membership areas:
<script>
document.addEventListener('DOMContentLoaded', function() {
// Track login form
const loginForm = document.querySelector('.wsite-membership-login-form');
if (loginForm) {
loginForm.addEventListener('submit', function() {
gtag('event', 'login', {
'method': 'weebly_membership',
'page_location': window.location.pathname
});
});
}
// Track sign up
const signupForm = document.querySelector('.wsite-membership-signup-form');
if (signupForm) {
signupForm.addEventListener('submit', function() {
gtag('event', 'sign_up', {
'method': 'weebly_membership',
'page_location': window.location.pathname
});
});
}
});
</script>
Error Tracking
Track 404 pages and errors:
<script>
// Track 404 pages
if (document.title.toLowerCase().includes('404') ||
document.querySelector('.wsite-404') ||
window.location.pathname.includes('/404')) {
gtag('event', 'exception', {
'description': '404_page_not_found',
'page_location': window.location.pathname,
'fatal': false
});
}
// Track JavaScript errors
window.addEventListener('error', function(e) {
gtag('event', 'exception', {
'description': 'JavaScript error: ' + e.message,
'fatal': false
});
});
</script>
Using Google Tag Manager for Events
For complex event tracking, GTM is recommended over manual code.
Advantages of GTM for Weebly
- No Weebly code changes needed after GTM installation
- Visual interface for creating triggers
- Built-in variables for clicks, forms, etc.
- Easy to test with Preview mode
- Version control and rollback capability
Example: Form Submission via GTM
1. Install GTM on Weebly
- See GTM Setup Guide
2. Create Form Submission Trigger
- Type: Form Submission
- Wait for Tags: Enable
- Check Validation: Enable
- Trigger fires on: All Forms
3. Create GA4 Event Tag
- Type: Google Analytics: GA4 Event
- Event Name:
form_submission - Event Parameters:
form_id:{{Form ID}}form_classes:{{Form Classes}}page_path:{{Page Path}}
- Trigger: Form Submission trigger
4. Test and Publish
- Use GTM Preview mode
- Submit a Weebly form
- Verify event fires in Tag Assistant
- Check in GA4 DebugView
- Publish container when confirmed
Testing & Debugging
1. GA4 DebugView
Enable debug mode temporarily (add to Header Code):
<script>
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
</script>
Then check Admin → DebugView in GA4 to see events in real-time with all parameters.
2. Browser Console Testing
Test events manually in browser console:
// Open browser console (F12) on your Weebly site
// Test an event:
gtag('event', 'test_event', {
'test_parameter': 'test_value'
});
// Then check GA4 Realtime or DebugView
3. Verify Events Are Firing
Check if gtag is loaded:
// In browser console:
console.log(typeof gtag);
// Should return "function", not "undefined"
// Check data layer:
console.log(window.dataLayer);
// Should show array with events
4. Common Testing Issues
Event doesn't fire:
- Check if selector matches element (use browser inspector)
- Ensure code is in Footer Code (runs after DOM loads)
- Check browser console for JavaScript errors
- Verify GA4 is installed correctly
Event fires multiple times:
- Check if code is added in multiple locations
- Use
{ once: true }option on event listeners - Add flags to prevent duplicate sends
Event Naming Best Practices
Recommended Event Names
Use GA4's recommended event names when possible:
view_item- Product viewsadd_to_cart- Add to cartbegin_checkout- Start checkoutpurchase- Completed purchase (not accessible on Weebly/Square)search- Site/blog searchsign_up- Account creationlogin- User login
Custom Event Naming
For custom events, follow these guidelines:
- Use lowercase
- Use underscores (snake_case)
- Be descriptive but concise
- Examples:
phone_call,newsletter_signup,blog_comment
Avoid:
- CamelCase:
formSubmission - Spaces:
form submission - Special characters:
form-submission! - Generic names:
click,event1
Event Parameters Best Practices
Common Parameters
Standard parameters to include:
page_location:window.location.pathnamepage_title:document.titlebutton_textorlink_text: Element text contentform_nameorform_id: Form identifier
Value and Currency
For ecommerce events:
value: Must be numeric (no symbols)currency: Use ISO 4217 code (USD, EUR, GBP, etc.)
Items Array
For product events, use proper structure:
'items': [{
'item_id': 'SKU123', // Product SKU or ID
'item_name': 'Product Name', // Product name
'price': 29.99, // Numeric price
'quantity': 1 // Quantity
}]
Common Issues
Events Fire Multiple Times
Cause: Event listeners added multiple times or duplicate code
Fix:
// Add 'once' option to event listeners
button.addEventListener('click', function() {
gtag('event', 'button_click', {
'button_text': this.textContent
});
}, { once: true });
Events Don't Fire
Causes:
- Element selector doesn't match Weebly's HTML
- Code runs before DOM is ready
- JavaScript error in console
Fix:
- Always wrap code in
DOMContentLoaded - Check browser console for errors (F12)
- Use browser inspector to find correct selectors
- Test in incognito mode (disable extensions)
Form Submissions Don't Track
Cause: Form submits and page reloads before event sends
Fix: Use event callback (though Weebly forms redirect, so this is limited):
form.addEventListener('submit', function(e) {
// GA4 will attempt to send before page unloads
gtag('event', 'form_submission', {
'transport_type': 'beacon' // Uses navigator.sendBeacon for reliability
});
// Don't prevent default - let Weebly handle form
});
Ecommerce Events Incomplete
Cause: Weebly uses Square for checkout, which is in iframe/separate domain
Solution:
- Accept limited ecommerce tracking on Weebly side
- Use Square Analytics for complete purchase data
- Track what you can: product views, add to cart, begin checkout
- Purchase event can't be tracked client-side on Weebly
Performance Considerations
Code Placement
Use Footer Code for tracking:
- Loads after page content
- Doesn't block page rendering
- Better for Core Web Vitals
Use Header Code only if:
- Need to track early page events
- Setting up data layer before GTM
- Implementing consent management
Minimize Code Weight
- Combine multiple event listeners into single scripts
- Avoid loading external libraries just for tracking
- Use GTM to consolidate tracking code
Test Performance Impact
Check site speed after adding tracking:
Privacy & Compliance
Cookie Consent
If you need cookie consent (GDPR, CCPA):
<script>
// Check consent before initializing GA4
if (localStorage.getItem('analytics_consent') === 'granted') {
gtag('consent', 'update', {
'analytics_storage': 'granted'
});
} else {
gtag('consent', 'default', {
'analytics_storage': 'denied'
});
}
</script>
User Privacy
Best practices:
- Don't track personally identifiable information (PII)
- Don't send email addresses or phone numbers to GA4
- Use hashed identifiers if needed
- Respect Do Not Track settings (optional)
Next Steps
- Install GTM - For easier event management
- Troubleshoot Events - Debug tracking issues
- GA4 Setup - Initial GA4 installation
- Weebly Performance - Optimize tracking impact
For general event tracking concepts, see GA4 Event Tracking Guide.