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

# Auto Track Plugin

> Automatically track page views, clicks, and viewability without manual instrumentation

## Overview

The AutoTrackPlugin automatically tracks common events based on DOM elements and user interactions, reducing manual tracking code.

## Installation

```typescript theme={null}
import { Refine, AutoTrackPlugin } from '@refine-ai/sdk';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789'
});

refine.use(new AutoTrackPlugin({
  pageViews: true,
  clicks: {
    selector: '[data-refine-item]',
    extractItemId: (el) => el.dataset.refineItem
  },
  viewability: {
    enabled: true,
    threshold: 0.5,
    duration: 1000
  }
}));
```

## Options

<ParamField body="pageViews" type="boolean" default="false">
  Automatically track page view events on navigation.
</ParamField>

<ParamField body="clicks" type="ClickConfig">
  Configuration for automatic click tracking.
</ParamField>

<ParamField body="viewability" type="ViewabilityConfig">
  Configuration for automatic viewability tracking.
</ParamField>

## Click Tracking

Automatically track clicks on product elements:

```typescript theme={null}
refine.use(new AutoTrackPlugin({
  clicks: {
    selector: '[data-refine-item]',
    extractItemId: (el) => el.dataset.refineItem,
    extractPosition: (el) => parseInt(el.dataset.position || '0')
  }
}));
```

### Click Config Options

<ParamField body="clicks.selector" type="string" required>
  CSS selector for clickable product elements.
</ParamField>

<ParamField body="clicks.extractItemId" type="(el: Element) => string" required>
  Function to extract the product ID from a clicked element.
</ParamField>

<ParamField body="clicks.extractPosition" type="(el: Element) => number">
  Function to extract the position from a clicked element. Defaults to 0.
</ParamField>

### HTML Setup for Click Tracking

```html theme={null}
<div class="product-grid">
  <div class="product" 
       data-refine-item="sku_001" 
       data-position="0">
    <img src="..." alt="Product 1" />
    <h3>Product Title</h3>
  </div>
  <div class="product" 
       data-refine-item="sku_002" 
       data-position="1">
    <img src="..." alt="Product 2" />
    <h3>Product Title</h3>
  </div>
</div>
```

## Viewability Tracking

Automatically track when products become visible:

```typescript theme={null}
refine.use(new AutoTrackPlugin({
  viewability: {
    enabled: true,
    selector: '[data-refine-item]',
    threshold: 0.5,    // 50% visible
    duration: 1000,    // for 1 second
    extractItemId: (el) => el.dataset.refineItem,
    extractPosition: (el) => parseInt(el.dataset.position || '0')
  }
}));
```

### Viewability Config Options

<ParamField body="viewability.enabled" type="boolean" default="false">
  Enable automatic viewability tracking.
</ParamField>

<ParamField body="viewability.selector" type="string">
  CSS selector for viewable elements. Defaults to clicks.selector.
</ParamField>

<ParamField body="viewability.threshold" type="number" default="0.5">
  Percentage of element that must be visible (0.0 to 1.0).
</ParamField>

<ParamField body="viewability.duration" type="number" default="1000">
  Milliseconds element must be visible before tracking.
</ParamField>

<ParamField body="viewability.extractItemId" type="(el: Element) => string">
  Function to extract product ID. Defaults to clicks.extractItemId.
</ParamField>

<ParamField body="viewability.extractPosition" type="(el: Element) => number">
  Function to extract position. Defaults to clicks.extractPosition.
</ParamField>

## Page View Tracking

Track page views automatically:

```typescript theme={null}
refine.use(new AutoTrackPlugin({
  pageViews: true
}));
```

This tracks:

* Initial page load
* SPA navigation (using History API)
* Hash changes

## Complete Configuration

```typescript theme={null}
import { Refine, AutoTrackPlugin } from '@refine-ai/sdk';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789'
});

refine.use(new AutoTrackPlugin({
  // Track page views
  pageViews: true,
  
  // Track clicks on product cards
  clicks: {
    selector: '[data-refine-item]',
    extractItemId: (el) => {
      return (el as HTMLElement).dataset.refineItem || '';
    },
    extractPosition: (el) => {
      return parseInt((el as HTMLElement).dataset.position || '0');
    }
  },
  
  // Track viewability
  viewability: {
    enabled: true,
    threshold: 0.5,
    duration: 1000
  }
}));
```

## HTML Data Attributes

The plugin expects specific data attributes on your product elements:

```html theme={null}
<!-- Search results -->
<div id="search-results" data-refine-surface="search_results" data-refine-source="text-search">
  <div class="product" 
       data-refine-item="sku_001" 
       data-position="0"
       data-refine-serve-id="srv_abc123">
    <!-- Product content -->
  </div>
</div>

<!-- Recommendations -->
<div id="similar-items" data-refine-surface="product_page" data-refine-source="similar-items">
  <div class="product" 
       data-refine-item="sku_002" 
       data-position="0"
       data-refine-serve-id="srv_xyz789">
    <!-- Product content -->
  </div>
</div>
```

### Required Attributes

| Attribute          | Purpose                             |
| ------------------ | ----------------------------------- |
| `data-refine-item` | Product ID for the element          |
| `data-position`    | Position in the results (0-indexed) |

### Optional Attributes

| Attribute              | Purpose                       |
| ---------------------- | ----------------------------- |
| `data-refine-surface`  | Where products are displayed  |
| `data-refine-source`   | How products were generated   |
| `data-refine-serve-id` | Links to original serve event |

## Dynamic Content

For dynamically loaded content, the plugin uses MutationObserver to detect new elements:

```typescript theme={null}
// New products added dynamically are automatically tracked
const newProduct = document.createElement('div');
newProduct.className = 'product';
newProduct.dataset.refineItem = 'sku_new';
newProduct.dataset.position = '24';

document.getElementById('search-results').appendChild(newProduct);
// Plugin automatically starts tracking this element
```

## Combining with Manual Tracking

You can use AutoTrackPlugin alongside manual tracking:

```typescript theme={null}
// Auto-track plugin handles clicks and views
refine.use(new AutoTrackPlugin({
  clicks: {
    selector: '[data-refine-item]',
    extractItemId: (el) => el.dataset.refineItem
  },
  viewability: { enabled: true, threshold: 0.5, duration: 1000 }
}));

// Manual tracking for search (to get the context)
const results = await refine.search.text({ query: 'shoes', topK: 24 });
const searchContext = refine.events.trackSearch('shoes', results.results, {
  surface: 'search_results',
  totalResults: results.totalResults
});

// Render products with data attributes
renderProducts(results.results);
// Auto-track plugin will handle click and view tracking
```

## Framework Integration

### React

```tsx theme={null}
import { useEffect } from 'react';
import { refine } from '@/lib/refine';
import { AutoTrackPlugin } from '@refine-ai/sdk';

export function ProductGrid({ products }) {
  useEffect(() => {
    // Plugin is typically initialized once at app level
    // But you can re-configure for specific pages
  }, []);

  return (
    <div data-refine-surface="search_results" data-refine-source="text-search">
      {products.map((product, index) => (
        <div
          key={product.productId}
          className="product"
          data-refine-item={product.productId}
          data-position={index}
        >
          <img src={product.imageUrl} alt={product.title} />
          <h3>{product.title}</h3>
          <p>${product.price}</p>
        </div>
      ))}
    </div>
  );
}
```

### Vue

```vue theme={null}
<template>
  <div data-refine-surface="search_results" data-refine-source="text-search">
    <div
      v-for="(product, index) in products"
      :key="product.productId"
      class="product"
      :data-refine-item="product.productId"
      :data-position="index"
    >
      <img :src="product.imageUrl" :alt="product.title" />
      <h3>{{ product.title }}</h3>
      <p>${{ product.price }}</p>
    </div>
  </div>
</template>
```

## Debugging Auto-Track

Combine with DebugPlugin to see what's being tracked:

```typescript theme={null}
refine.use(new DebugPlugin({ logEvents: true }));
refine.use(new AutoTrackPlugin({
  pageViews: true,
  clicks: { selector: '[data-refine-item]', extractItemId: el => el.dataset.refineItem },
  viewability: { enabled: true, threshold: 0.5, duration: 1000 }
}));

// Console will show:
// [Refine AutoTrack] Click detected: sku_001 at position 3
// [Refine AutoTrack] View tracked: sku_002 at position 0
// [Refine AutoTrack] Page view: /products/shoes
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Debug Plugin" icon="bug" href="/sdk/plugins/debug-plugin">
    Development tools
  </Card>

  <Card title="Consent Plugin" icon="shield-check" href="/sdk/plugins/consent-plugin">
    Privacy compliance
  </Card>
</CardGroup>
