> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grainql.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Grain Tag (Script)

> Add Grain Analytics without npm or a build step

The primary way to install Grain. Perfect for any website — landing pages, static sites, CMSs, or full web apps. No build tools required.

Grain Tag automatically tracks page views, clicks, scroll depth, heatmaps, and DOM snapshots with zero code. Just add the script and you're collecting data.

<Note>
  **Using React or Next.js?** Try [React Quick Start](/quickstart/react) or [Next.js Quick Start](/quickstart/nextjs) for framework-specific integration.
</Note>

## Add the Script Tag

Add this to your HTML `<head>`:

```html theme={null}
<script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
```

Replace `your-tenant-id` with your tenant identifier (not UUID) from your [dashboard](https://grainql.com/dashboard).

That's it! Grain is now loaded and tracking page views, heatmap clicks, scroll depth, and DOM snapshots automatically.

## Complete HTML Example

```html theme={null}
<!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 Custom Events

```javascript theme={null}
const grain = GrainTag.getInstance();

grain.track('button_clicked', {
  button_name: 'signup',
  location: 'hero'
});
```

You can also use the top-level shortcut:

```javascript theme={null}
GrainTag.track('button_clicked', {
  button_name: 'signup',
  location: 'hero'
});
```

Events are automatically batched and sent. No manual flushing needed.

## Track Form Submissions

```html theme={null}
<form id="contact-form">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <button type="submit">Submit</button>
</form>

<script>
  const grain = GrainTag.getInstance();

  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

```html theme={null}
<a href="/pricing" id="pricing-link">View Pricing</a>

<script>
  const grain = GrainTag.getInstance();

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

## Identify Users

Track logged-in users:

```html theme={null}
<script>
  const grain = GrainTag.getInstance();

  // When user logs in — pass only the user ID
  function handleLogin(userId) {
    grain.identify(userId);

    // Track login event
    grain.track('user_logged_in', {
      method: 'email'
    });
  }
</script>
```

## Consent Management

Grain is cookieless by default with daily rotating IDs. When you need explicit consent handling:

```html theme={null}
<script>
  const grain = GrainTag.getInstance();

  // Grant consent (enables persistent tracking)
  grain.consent.grant();

  // Revoke consent
  grain.consent.revoke();

  // Check consent status
  const status = grain.consent.status();
</script>
```

## SPA Navigation

Grain Tag automatically tracks page views on initial load and hooks into the History API (`pushState` / `replaceState`) to track navigation in single-page apps. No manual page view tracking is needed for most SPAs.

If your app uses custom routing that does not go through the History API, you can track navigation manually:

```html theme={null}
<script>
  const grain = GrainTag.getInstance();

  // Only needed for custom routing that bypasses the History API
  function navigateTo(url) {
    // Your custom navigation logic...
    grain.track('page_viewed', {
      page: url
    });
  }
</script>
```

## Performance Tips

<Check>
  **Do**: Place Grain in the `<head>` for early initialization
</Check>

<Check>
  **Do**: Use one script tag per page — Grain handles everything
</Check>

<Warning>
  **Don't**: Load Grain multiple times — once per page is enough
</Warning>

## What's Next?

<CardGroup cols={2}>
  <Card title="Core API Reference" icon="book" href="/api-reference/core-methods">
    See all available methods and options
  </Card>

  <Card title="Event Tracking Guide" icon="chart-line" href="/core/event-tracking">
    Learn what to track and best practices
  </Card>

  <Card title="Trackers" icon="crosshairs" href="/features/trackers">
    Track element clicks without code
  </Card>

  <Card title="Vanilla JS, Vue & Svelte" icon="code" href="/quickstart/vanilla-js">
    Integration with other frameworks
  </Card>
</CardGroup>

<Tip>
  **Using Google Tag Manager instead?** Check out the [GTM Integration Guide](/integrations/gtm) for a no-code setup.
</Tip>

<Note>
  **Need remote configuration or feature flags?** See [@grainql/analytics-web](/react/overview) for remote config support.
</Note>
