Skip to content

Declarative Tracking

Declarative tracking uses data-fanfest-* HTML attributes to track user interactions. The SDK automatically discovers annotated elements, attaches event listeners, and reports actions to FanFest. When elements are added or removed from the DOM, the SDK updates its tracking via a MutationObserver — no manual cleanup is needed.

This approach is ideal for CMS-managed content, static sites, and server-rendered pages where you want to add tracking without writing JavaScript.

Data Attributes

The SDK recognizes 6 data attributes. All values come from the TrackDataAttribute enum in the SDK source.

data-fanfest-track (required)

The action name or alias to track. This must match a key you registered with registerActionMapping().

html
<button data-fanfest-track="READ_ARTICLE">Read More</button>

data-fanfest-on

The DOM event that triggers the tracking action. If omitted, defaults to click.

html
<button data-fanfest-track="READ_ARTICLE" data-fanfest-on="click">
  Read More
</button>

Supported events (only these 3 are recognized):

EventDescriptionUse Case
clickMouse click or tap (default)Buttons, links, cards
renderFires immediately when the element is set up by the SDKSection views, impression tracking
submitForm submissionNewsletter signups, contact forms

Only 3 Events Supported

The SDK only supports click, render, and submit. Other DOM events (scroll, input, timeupdate, etc.) are not tracked declaratively. For custom events, use the imperative API.

data-fanfest-description

A human-readable description of the action. Appears in analytics and can help distinguish between similar actions.

html
<button
  data-fanfest-track="purchase"
  data-fanfest-description="Premium Plan Annual"
>
  Buy Now
</button>

data-fanfest-experience-id

Groups related actions into a logical experience or flow. Useful for tracking multi-step funnels.

html
<div
  data-fanfest-track="CHECKOUT_VIEW"
  data-fanfest-on="render"
  data-fanfest-experience-id="checkout-flow"
>
  <!-- Checkout content -->
</div>

data-fanfest-object-id

A unique identifier for the specific object being interacted with (e.g., an article ID, product SKU, or page slug).

html
<button
  data-fanfest-track="READ_ARTICLE"
  data-fanfest-on="click"
  data-fanfest-object-id="article-2024-champions-league"
>
  Read Article
</button>

Choose Stable IDs

Use meaningful, stable identifiers like article-champions-league-final rather than DOM-dependent values like button-3. Stable IDs produce better analytics.

data-fanfest-meta-*

Custom key-value metadata. Any attribute prefixed with data-fanfest-meta- is collected into a metadata object. The portion after data-fanfest-meta- becomes the key.

html
<button
  data-fanfest-track="purchase"
  data-fanfest-on="click"
  data-fanfest-object-id="product-123"
  data-fanfest-meta-campaign="BlackFriday"
  data-fanfest-meta-amount="99.99"
  data-fanfest-meta-currency="USD"
>
  Buy Now - $99.99
</button>

This produces the metadata object { campaign: "BlackFriday", amount: "99.99", currency: "USD" }.

INFO

All data-fanfest-meta-* values are strings in declarative tracking (HTML attributes are always strings). For typed values, use the imperative API.

Attribute Reference

AttributeRequiredDescription
data-fanfest-trackYesAction name or alias (must match a registered mapping)
data-fanfest-onNoTrigger event: click (default), render, or submit
data-fanfest-descriptionNoHuman-readable action description
data-fanfest-experience-idNoGroups related actions into a flow
data-fanfest-object-idNoUnique identifier for the tracked object
data-fanfest-meta-*NoCustom metadata key-value pairs

Event Modifiers

Modifiers control event listener behavior. Append them to the event name in data-fanfest-on separated by colons. Modifiers correspond to the TrackEventModifier enum in the SDK.

Available modifiers:

ModifierEffect
stopCalls event.stopPropagation()
preventDefaultCalls event.preventDefault() and sets passive: false on the listener
captureAttaches the listener in the capture phase
onceFires the listener only once, then removes it

Use Full Modifier Names

Modifiers must use their full names exactly as shown. For example, use preventDefault (not prevent) and stop (not stopPropagation).

Modifier Syntax

Append modifiers after the event name, separated by colons:

data-fanfest-on="<event>:<modifier1>:<modifier2>"

Examples

html
<!-- Prevent default form submission behavior -->
<form
  data-fanfest-track="newsletter_signup"
  data-fanfest-on="submit:preventDefault"
>
  <input type="email" required />
  <button type="submit">Subscribe</button>
</form>

<!-- Track only the first click -->
<button
  data-fanfest-track="first_interaction"
  data-fanfest-on="click:once"
>
  Welcome Offer
</button>

<!-- Stop propagation to parent handlers -->
<button
  data-fanfest-track="isolated_click"
  data-fanfest-on="click:stop"
>
  Isolated Button
</button>

<!-- Capture phase listener -->
<div
  data-fanfest-track="early_capture"
  data-fanfest-on="click:capture"
>
  Captured Area
</div>

Combining Modifiers

Multiple modifiers can be chained:

html
<!-- Prevent default and fire only once -->
<form
  data-fanfest-track="signup"
  data-fanfest-on="submit:preventDefault:once"
  data-fanfest-description="One-time Newsletter Signup"
  data-fanfest-object-id="newsletter-form"
>
  <input type="email" placeholder="Enter your email" required />
  <button type="submit">Subscribe</button>
</form>

<!-- Stop propagation, prevent default, capture phase -->
<button
  data-fanfest-track="priority_action"
  data-fanfest-on="click:stop:preventDefault:capture"
>
  Priority Action
</button>

How It Works

  1. When the SDK initializes, it scans the DOM for elements with data-fanfest-track
  2. For each element, it reads the event type from data-fanfest-on (defaulting to click)
  3. For render events, the tracking action fires immediately when the element is discovered
  4. For click and submit events, the SDK attaches an event listener with the specified modifiers
  5. A MutationObserver watches for DOM changes — new elements are automatically tracked, removed elements are cleaned up

When to Use Declarative Tracking

  • CMS-managed content (WordPress, Contentful, etc.)
  • Static HTML pages and landing pages
  • Server-rendered pages (SSR)
  • Simple tracking where no conditional logic is needed
  • Non-technical content editors managing tracked elements

For dynamic content, conditional tracking, or typed metadata values, use the imperative API.

Accessibility

Tracking attributes do not affect accessibility. Ensure your tracked elements are already accessible:

html
<!-- Accessible button with tracking -->
<button
  data-fanfest-track="cta_click"
  data-fanfest-on="click"
  aria-label="Get started with FanFest"
>
  Get Started
</button>

<!-- Accessible form with tracking -->
<form
  data-fanfest-track="contact_submit"
  data-fanfest-on="submit:preventDefault"
>
  <label for="email">Email</label>
  <input id="email" type="email" required />
  <button type="submit">Subscribe</button>
</form>

Next Steps

Released under the MIT License.