Perfect for landing pages, static sites, or quick prototypes. No build tools required—just add a script tag.
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>
<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>
Track Link Clicks
<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>
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?