Skip to main content
10 min read

Vanilla JavaScript Integration Example

This guide provides a complete, production-ready example of integrating Zenovay analytics using plain JavaScript without any framework. Perfect for static sites, traditional web applications, or learning the fundamentals.

Quick Start

Add the Zenovay tracking script to your HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Website</title>

  <!-- Zenovay Analytics -->
  <script src="https://api.zenovay.com/z.js"
          data-tracking-code="YOUR_TRACKING_CODE"
          async></script>
</head>
<body>
  <h1>Welcome to My Website</h1>
</body>
</html>

That's it! Page views are now tracked automatically.

Basic Setup

1. Install Script in HTML

Add the script tag to your <head> section:

<head>
  <!-- Other head elements -->

  <!-- Zenovay Analytics -->
  <script src="https://api.zenovay.com/z.js"
          data-tracking-code="YOUR_TRACKING_CODE"
          async></script>
</head>

Important attributes:

  • data-tracking-code: Your unique site ID from the Zenovay dashboard
  • async: Loads script asynchronously for better performance

2. Track Custom Events

Track events using the global window.zenovay object:

<button onclick="handleSignup()">Start Free Trial</button>

<script>
  function handleSignup() {
    if (window.zenovay) {
      window.zenovay('track', 'signup_started', {
        plan: 'professional',
        source: 'pricing_page'
      });
    }

    // Continue with signup logic
    window.location.href = '/signup';
  }
</script>

3. Wait for Script Load

If you need to ensure Zenovay is loaded:

<script>
  // Wait for Zenovay to be ready
  window.addEventListener('zenovay:ready', function() {
    console.log('Zenovay is ready!');

    // Now safe to track events
    window.zenovay('track', 'page_loaded');
  });
</script>

Complete Example

Here's a full HTML page with comprehensive Zenovay integration:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>E-commerce Store - Zenovay Example</title>

  <!-- Zenovay Analytics -->
  <script src="https://api.zenovay.com/z.js"
          data-tracking-code="YOUR_TRACKING_CODE"
          async></script>

  <style>
    body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
    .product { border: 1px solid #ddd; padding: 20px; margin: 10px; display: inline-block; }
    button { background: #007bff; color: white; border: none; padding: 10px 20px; cursor: pointer; }
    button:hover { background: #0056b3; }
  </style>
</head>
<body>
  <h1>My E-commerce Store</h1>

  <div class="product" data-product-id="prod_123">
    <h2>Premium Headphones</h2>
    <p>Price: $299</p>
    <button onclick="addToCart('prod_123', 'Premium Headphones', 299)">
      Add to Cart
    </button>
  </div>

  <div class="product" data-product-id="prod_456">
    <h2>Wireless Mouse</h2>
    <p>Price: $49</p>
    <button onclick="addToCart('prod_456', 'Wireless Mouse', 49)">
      Add to Cart
    </button>
  </div>

  <script>
    // Wait for Zenovay to load
    window.addEventListener('zenovay:ready', function() {
      console.log('Zenovay analytics ready');

      // Track products viewed on page
      trackProductsViewed();
    });

    // Track product views
    function trackProductsViewed() {
      const products = document.querySelectorAll('.product');

      products.forEach(function(product) {
        const productId = product.getAttribute('data-product-id');
        const productName = product.querySelector('h2').textContent;
        const priceText = product.querySelector('p').textContent;
        const price = parseFloat(priceText.replace(/[^0-9.]/g, ''));

        if (window.zenovay) {
          window.zenovay('track', 'product_viewed', {
            product_id: productId,
            product_name: productName,
            price: price,
            currency: 'USD'
          });
        }
      });
    }

    // Track add to cart
    function addToCart(productId, productName, price) {
      if (window.zenovay) {
        window.zenovay('track', 'product_added_to_cart', {
          product_id: productId,
          product_name: productName,
          price: price,
          quantity: 1,
          total: price
        });
      }

      alert('Added to cart: ' + productName);
    }
  </script>
</body>
</html>

Advanced Patterns

Event Tracking Helper

Create a reusable tracking utility:

<script>
  // Analytics utility object
  var Analytics = (function() {
    var isReady = false;
    var queue = [];

    // Check if Zenovay is loaded
    function checkReady() {
      return typeof window.zenovay !== 'undefined';
    }

    // Process queued events
    function processQueue() {
      while (queue.length > 0) {
        var event = queue.shift();
        track(event.name, event.data);
      }
    }

    // Listen for ready event
    window.addEventListener('zenovay:ready', function() {
      isReady = true;
      processQueue();
    });

    // Track event (with queue fallback)
    function track(eventName, eventData) {
      if (checkReady()) {
        window.zenovay('track',eventName, eventData || {});
      } else {
        queue.push({ name: eventName, data: eventData });
      }
    }

    // Track pageview
    function trackPageview(data) {
      if (checkReady()) {
        window.zenovay('page');
      }
    }

    // Identify user
    function identify(userId, traits) {
      if (checkReady()) {
        window.zenovay('identify',userId, traits || {});
      }
    }

    // Public API
    return {
      track: track,
      trackPageview: trackPageview,
      identify: identify,
      isReady: function() { return isReady; }
    };
  })();

  // Usage
  Analytics.track('button_clicked', { button_name: 'signup' });
</script>

Form Tracking

Track form interactions:

<form id="contact-form" onsubmit="return handleFormSubmit(event)">
  <input type="text" name="name" placeholder="Name" required
         onfocus="trackFieldFocus('name')">

  <input type="email" name="email" placeholder="Email" required
         onfocus="trackFieldFocus('email')">

  <textarea name="message" placeholder="Message" required
            onfocus="trackFieldFocus('message')"></textarea>

  <button type="submit">Send Message</button>
</form>

<script>
  function trackFieldFocus(fieldName) {
    if (window.zenovay) {
      window.zenovay('track', 'form_field_focused', {
        form_id: 'contact',
        field_name: fieldName
      });
    }
  }

  function handleFormSubmit(event) {
    event.preventDefault();

    const form = document.getElementById('contact-form');
    const formData = new FormData(form);

    // Track form submission
    if (window.zenovay) {
      window.zenovay('track', 'contact_form_submitted', {
        form_id: 'contact',
        has_message: formData.get('message').length > 0
      });
    }

    // Submit form logic
    console.log('Form submitted:', Object.fromEntries(formData));

    return false;
  }
</script>

E-commerce Tracking Module

Complete e-commerce tracking:

<script>
  var EcommerceTracking = (function() {
    function trackProductView(product) {
      if (window.zenovay) {
        window.zenovay('track', 'product_viewed', {
          product_id: product.id,
          product_name: product.name,
          category: product.category,
          price: product.price,
          currency: 'USD'
        });
      }
    }

    function trackAddToCart(product, quantity) {
      quantity = quantity || 1;

      if (window.zenovay) {
        window.zenovay('track', 'product_added_to_cart', {
          product_id: product.id,
          product_name: product.name,
          quantity: quantity,
          price: product.price,
          total: product.price * quantity
        });
      }
    }

    function trackCheckout(cart) {
      if (window.zenovay) {
        window.zenovay('track', 'checkout_started', {
          cart_total: cart.total,
          item_count: cart.items.length,
          currency: 'USD'
        });
      }
    }

    function trackPurchase(order) {
      if (window.zenovay) {
        window.zenovay('track', 'purchase_completed', {
          order_id: order.id,
          revenue: order.total,
          tax: order.tax,
          shipping: order.shipping,
          currency: 'USD',
          items: order.items.map(function(item) {
            return {
              product_id: item.id,
              quantity: item.quantity,
              price: item.price
            };
          })
        });
      }
    }

    return {
      trackProductView: trackProductView,
      trackAddToCart: trackAddToCart,
      trackCheckout: trackCheckout,
      trackPurchase: trackPurchase
    };
  })();

  // Usage
  EcommerceTracking.trackProductView({
    id: 'prod_123',
    name: 'Premium Headphones',
    category: 'Electronics',
    price: 299
  });
</script>

Click Tracking

Automatically track button clicks:

<script>
  // Track all button clicks
  document.addEventListener('DOMContentLoaded', function() {
    var buttons = document.querySelectorAll('button[data-track]');

    buttons.forEach(function(button) {
      button.addEventListener('click', function() {
        var eventName = this.getAttribute('data-track');
        var eventData = this.getAttribute('data-track-data');

        if (window.zenovay && eventName) {
          var data = eventData ? JSON.parse(eventData) : {};
          data.button_text = this.textContent;
          data.button_id = this.id || 'unknown';

          window.zenovay('track',eventName, data);
        }
      });
    });
  });
</script>

<!-- Usage -->
<button data-track="cta_clicked"
        data-track-data='{"location":"hero","type":"primary"}'>
  Get Started
</button>

Scroll Tracking

Track how far users scroll:

<script>
  (function() {
    var maxScroll = 0;
    var checkpoints = [25, 50, 75, 100];
    var reached = {};

    function calculateScrollPercentage() {
      var windowHeight = window.innerHeight;
      var documentHeight = document.documentElement.scrollHeight;
      var scrollTop = window.pageYOffset || document.documentElement.scrollTop;

      var scrollPercentage = (scrollTop / (documentHeight - windowHeight)) * 100;
      return Math.round(scrollPercentage);
    }

    function trackScrollDepth() {
      var scrollPercentage = calculateScrollPercentage();

      if (scrollPercentage > maxScroll) {
        maxScroll = scrollPercentage;
      }

      checkpoints.forEach(function(checkpoint) {
        if (scrollPercentage >= checkpoint && !reached[checkpoint]) {
          reached[checkpoint] = true;

          if (window.zenovay) {
            window.zenovay('track', 'scroll_depth', {
              percentage: checkpoint,
              page: window.location.pathname
            });
          }
        }
      });
    }

    // Throttle scroll events
    var scrollTimeout;
    window.addEventListener('scroll', function() {
      clearTimeout(scrollTimeout);
      scrollTimeout = setTimeout(trackScrollDepth, 300);
    });
  })();
</script>

Time on Page

Track how long users spend on page:

<script>
  (function() {
    var startTime = Date.now();
    var intervals = [30, 60, 120, 300]; // seconds
    var tracked = {};

    function trackTimeOnPage() {
      var timeSpent = Math.floor((Date.now() - startTime) / 1000);

      intervals.forEach(function(interval) {
        if (timeSpent >= interval && !tracked[interval]) {
          tracked[interval] = true;

          if (window.zenovay) {
            window.zenovay('track', 'time_on_page', {
              seconds: interval,
              page: window.location.pathname
            });
          }
        }
      });
    }

    // Check every 5 seconds
    setInterval(trackTimeOnPage, 5000);

    // Track on page unload
    window.addEventListener('beforeunload', function() {
      var timeSpent = Math.floor((Date.now() - startTime) / 1000);

      if (window.zenovay && timeSpent >= 5) {
        window.zenovay('track', 'page_exit', {
          time_spent: timeSpent,
          page: window.location.pathname
        });
      }
    });
  })();
</script>

User Identification

Identify logged-in users:

<script>
  // After user logs in
  function identifyUser(user) {
    if (window.zenovay) {
      window.zenovay('identify',user.id, {
        email: user.email,
        name: user.name,
        plan: user.subscription.plan,
        signup_date: user.createdAt
      });
    }
  }

  // Check if user is logged in on page load
  window.addEventListener('DOMContentLoaded', function() {
    var user = getCurrentUser(); // Your function to get logged-in user

    if (user) {
      identifyUser(user);
    }
  });

  // Example user object
  function getCurrentUser() {
    // This would typically come from your backend
    return {
      id: 'user_123',
      email: '[email protected]',
      name: 'John Doe',
      subscription: { plan: 'professional' },
      createdAt: '2024-01-01'
    };
  }
</script>

Error Tracking

Automatically track JavaScript errors:

<script>
  window.addEventListener('error', function(event) {
    if (window.zenovay) {
      window.zenovay('track', 'javascript_error', {
        error_message: event.message,
        error_filename: event.filename,
        error_line: event.lineno,
        error_column: event.colno,
        page: window.location.pathname,
        user_agent: navigator.userAgent
      });
    }
  });

  // Track unhandled promise rejections
  window.addEventListener('unhandledrejection', function(event) {
    if (window.zenovay) {
      window.zenovay('track', 'promise_rejection', {
        reason: event.reason ? event.reason.toString() : 'Unknown',
        page: window.location.pathname
      });
    }
  });
</script>

Single Page Application (SPA) Pattern

Track route changes in SPAs:

<script>
  // Detect route changes
  (function() {
    var lastPath = window.location.pathname;

    // Override pushState and replaceState
    var originalPushState = history.pushState;
    var originalReplaceState = history.replaceState;

    history.pushState = function() {
      originalPushState.apply(this, arguments);
      trackRouteChange();
    };

    history.replaceState = function() {
      originalReplaceState.apply(this, arguments);
      trackRouteChange();
    };

    // Listen for popstate (back/forward buttons)
    window.addEventListener('popstate', trackRouteChange);

    function trackRouteChange() {
      var currentPath = window.location.pathname;

      if (currentPath !== lastPath) {
        lastPath = currentPath;

        if (window.zenovay) {
          window.zenovay('page');
        }
      }
    }
  })();
</script>

Performance Optimization

Debounce Helper

Prevent excessive tracking:

<script>
  // Debounce utility
  function debounce(func, wait) {
    var timeout;
    return function() {
      var context = this;
      var args = arguments;

      clearTimeout(timeout);
      timeout = setTimeout(function() {
        func.apply(context, args);
      }, wait);
    };
  }

  // Usage: Debounce search tracking
  var searchInput = document.getElementById('search');

  var trackSearch = debounce(function(query) {
    if (window.zenovay) {
      window.zenovay('track', 'search_performed', {
        query: query,
        length: query.length
      });
    }
  }, 500);

  searchInput.addEventListener('input', function(e) {
    trackSearch(e.target.value);
  });
</script>

Lazy Load Script

Load Zenovay only after page is interactive:

<script>
  // Load Zenovay after page is interactive
  window.addEventListener('load', function() {
    var script = document.createElement('script');
    script.src = 'https://api.zenovay.com/z.js';
    script.setAttribute('data-tracking-code', 'YOUR_TRACKING_CODE');
    script.async = true;
    document.head.appendChild(script);
  });
</script>

Integrate with cookie consent banners:

<script>
  // Wait for user consent before tracking
  function initializeAnalytics() {
    var script = document.createElement('script');
    script.src = 'https://api.zenovay.com/z.js';
    script.setAttribute('data-tracking-code', 'YOUR_TRACKING_CODE');
    script.async = true;
    document.head.appendChild(script);
  }

  // Check consent (example with localStorage)
  function checkConsent() {
    return localStorage.getItem('analytics_consent') === 'true';
  }

  // Initialize if consent given
  if (checkConsent()) {
    initializeAnalytics();
  }

  // Listen for consent acceptance
  window.addEventListener('consent:accepted', function() {
    localStorage.setItem('analytics_consent', 'true');
    initializeAnalytics();
  });
</script>

<!-- Simple consent banner -->
<div id="consent-banner" style="display: none;">
  <p>We use analytics to improve your experience.</p>
  <button onclick="acceptConsent()">Accept</button>
</div>

<script>
  if (!checkConsent()) {
    document.getElementById('consent-banner').style.display = 'block';
  }

  function acceptConsent() {
    document.getElementById('consent-banner').style.display = 'none';
    window.dispatchEvent(new Event('consent:accepted'));
  }
</script>

Configuration Options

Advanced script configuration:

<!-- Custom domain -->
<script src="https://analytics.yourdomain.com/z.js"
        data-tracking-code="YOUR_TRACKING_CODE"
        async></script>

<!-- Debug mode -->
<script src="https://api.zenovay.com/z.js"
        data-tracking-code="YOUR_TRACKING_CODE"
        data-debug="true"
        async></script>

WordPress Integration

Add to WordPress without a plugin:

// Add to your theme's functions.php
function add_zenovay_tracking() {
  ?>
  <script src="https://api.zenovay.com/z.js"
          data-tracking-code="YOUR_TRACKING_CODE"
          async></script>
  <?php
}
add_action('wp_head', 'add_zenovay_tracking');

Shopify Integration

Add to Shopify theme:

<!-- Add to theme.liquid, before </head> -->
<script src="https://api.zenovay.com/z.js"
        data-tracking-code="YOUR_TRACKING_CODE"
        async></script>

<!-- Track purchases on thank you page -->
{% if checkout.id %}
<script>
  window.addEventListener('zenovay:ready', function() {
    window.zenovay('track', 'purchase_completed', {
      order_id: '{{ checkout.order_id }}',
      revenue: {{ checkout.total_price | money_without_currency }},
      currency: '{{ shop.currency }}',
      items: [
        {% for line_item in checkout.line_items %}
        {
          product_id: '{{ line_item.product_id }}',
          quantity: {{ line_item.quantity }},
          price: {{ line_item.price | money_without_currency }}
        }{% unless forloop.last %},{% endunless %}
        {% endfor %}
      ]
    });
  });
</script>
{% endif %}

Testing

Test your integration:

<script>
  // Enable debug mode
  window.zenovay('debug');

  // Test tracking
  window.addEventListener('zenovay:ready', function() {
    console.log('Zenovay ready, running tests...');

    // Test 1: Track custom event
    window.zenovay('track', 'test_event', { test: true });
    console.log('Event tracking called');

    // Test 2: Track pageview
    window.zenovay('page');
    console.log('Pageview tracking called');
  });
</script>

Browser Compatibility

Zenovay supports all modern browsers:

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+
  • Opera 76+

For older browsers, consider using polyfills:

<!-- Polyfill for older browsers -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=Promise%2Cfetch"></script>

<!-- Then load Zenovay -->
<script src="https://api.zenovay.com/z.js"
        data-tracking-code="YOUR_TRACKING_CODE"
        async></script>

Environment Variables

For build tools like Webpack or Vite:

<!-- Development -->
<script>
  var ZENOVAY_TRACKING_CODE = 'dev_site_id';
  var ZENOVAY_DEBUG = true;
</script>

<!-- Production (replace with build tool) -->
<script>
  var ZENOVAY_TRACKING_CODE = '<!-- ZENOVAY_TRACKING_CODE -->';
  var ZENOVAY_DEBUG = false;
</script>

<script src="https://api.zenovay.com/z.js"
        data-tracking-code="YOUR_TRACKING_CODE"
        async></script>

Additional Resources

Was this page helpful?