Skip to main content
Perfect for landing pages, static sites, or quick prototypes. No build tools required—just add a script tag.
Building an app with a bundler? Try Vanilla JS Quick Start or React Quick Start for better tree-shaking and bundle optimization.

Add the Script Tag

Add this to your HTML <head>:
<script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
<script>
  // SDK auto-initializes, get the instance
  const grain = GrainTag.getInstance();
  
  // Track custom events
  grain.track('button_clicked', {
    button_id: 'signup'
  });
</script>
Replace your-tenant-id with your tenant identifier (not UUID) from your dashboard. That’s it! Grain is now loaded and tracking.

Complete HTML Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Landing Page</title>
  
  <!-- Grain Tag (auto-initializes) -->
  <script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
</head>
<body>
  <h1>Welcome!</h1>
  <button id="signup-btn">Get Started</button>
  
  <script>
    // Get SDK instance (already initialized)
    const grain = GrainTag.getInstance();
    
    // Track button clicks
    document.getElementById('signup-btn').addEventListener('click', function() {
      grain.track('signup_clicked', {
        location: 'hero'
      });
      
      // Your signup logic...
      window.location.href = '/signup';
    });
  </script>
</body>
</html>

Track Form Submissions

<form id="contact-form">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <button type="submit">Submit</button>
</form>

<script>
  document.getElementById('contact-form').addEventListener('submit', function(e) {
    e.preventDefault();
    
    // Track the submission
    grain.track('form_submitted', {
      form_name: 'contact',
      page: window.location.pathname
    });
    
    // Your form submission logic...
  });
</script>
<a href="/pricing" id="pricing-link">View Pricing</a>

<script>
  document.getElementById('pricing-link').addEventListener('click', function() {
    grain.track('link_clicked', {
      link_text: 'View Pricing',
      destination: '/pricing'
    });
  });
</script>

Use Remote Configuration

Control your page content without redeploying:
<div id="promo-banner" style="display: none;">
  <p id="promo-text">Special offer!</p>
</div>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Check if banner should show
    const showBanner = grain.getConfig('show_promo_banner');
    const bannerText = grain.getConfig('promo_banner_text');
    
    if (showBanner === 'true') {
      document.getElementById('promo-banner').style.display = 'block';
      document.getElementById('promo-text').textContent = bannerText || 'Special offer!';
    }
  });
</script>
Now you can toggle the banner on/off from your dashboard without touching your code!

Identify Users

Track logged-in users:
<script>
  // When user logs in
  function handleLogin(userId, email, name) {
    grain.identify(userId, {
      email: email,
      name: name,
      signup_date: new Date().toISOString()
    });
    
    // Track login event
    grain.track('user_logged_in', {
      method: 'email'
    });
  }
</script>

Track Page Views on Navigation

For multi-page sites, the script automatically tracks each page load. For single-page apps:
<script>
  // Track browser back/forward
  window.addEventListener('popstate', function() {
    grain.track('page_viewed', {
      page: window.location.pathname
    });
  });
  
  // Track custom navigation
  function navigateTo(url) {
    history.pushState(null, '', url);
    
    grain.track('page_viewed', {
      page: url
    });
    
    // Your navigation logic...
  }
</script>

Version Pinning

By default, unpkg.com serves the latest version. For production, pin to a specific version:
<!-- Pin to a specific version -->
<script src="https://unpkg.com/@grainql/[email protected]/dist/index.global.js"></script>
Check the npm package for available versions.

Alternative CDNs

You can also use these CDNs:
<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@grainql/analytics-web/dist/index.global.js"></script>

<!-- unpkg (default) -->
<script src="https://unpkg.com/@grainql/analytics-web/dist/index.global.js"></script>

Performance Tips

Do: Place Grain in the <head> for early initialization
Do: Use defer or async if you need to delay loading:
<script defer src="https://unpkg.com/@grainql/analytics-web/dist/index.global.js"></script>
Do: Pin to a specific version in production
Don’t: Load Grain multiple times—once per page is enough

What’s Next?

Using Google Tag Manager instead? Check out the GTM Integration Guide for a no-code setup.