Skip to content

Page View Tracking Examples

Track page views across different platforms and routing systems with the FanFest SDK.

CMS/WordPress Examples

Automatic Page View Tracking

The SDK automatically tracks page views when initialized:

html
<script src="https://sdk.production.fanfest.vip/1.0.20/esm/fanfest-sdk.esm.js"></script>
<script>
  FanFestSDK.init({
    apiKey: "your-api-key",
    clientId: "your-client-id",
  });
  // Page view is automatically tracked
</script>

Section-Based Tracking with Vue.js

Here's how to track different sections with render events:

vue
<template>
  <!-- Video section tracking -->
  <div
    :data-fanfest-track="EngagementAction.BROWSED_VIDEOS"
    :data-fanfest-description="EngagementAction.BROWSED_VIDEOS"
    data-fanfest-experience-id="BROWSED_VIDEOS"
    data-fanfest-on="render"
  >
    <!-- Video content -->
  </div>

  <!-- News section tracking -->
  <div
    class="bg-gray-100"
    :data-fanfest-track="EngagementAction.BROWSED_NEWS"
    :data-fanfest-description="EngagementAction.BROWSED_NEWS"
    data-fanfest-experience-id="BROWSED_NEWS"
    data-fanfest-on="render"
  >
    <!-- News content -->
  </div>
</template>

Manual Page View Tracking

For more control, track page views manually:

html
<body data-fanfest-track="page_view" data-fanfest-on="render">
  <!-- Your page content -->
</body>

WordPress Theme Integration

php
// In your WordPress theme's functions.php
function fanfest_page_view_tracking() {
    if (!is_admin()) {
        ?>
        <script>
        FanFestSDK.trackEvent({
            action: 'page_view',
            description: '<?php echo esc_js(get_the_title()); ?>',
            externalObjectId: '<?php echo esc_js(get_the_ID()); ?>',
            metadata: {
                postType: '<?php echo esc_js(get_post_type()); ?>',
                category: '<?php echo esc_js(get_the_category()[0]->name ?? ''); ?>'
            }
        });
        </script>
        <?php
    }
}
add_action('wp_footer', 'fanfest_page_view_tracking');

React/SPA Examples

React Router Integration

jsx
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
// FanFestSDK is available globally after loading the SDK script

function App() {
  const location = useLocation();

  useEffect(() => {
    // Track page view on route change
    FanFestSDK.trackEvent({
      action: "page_view",
      description: document.title,
      externalObjectId: location.pathname,
      metadata: {
        route: location.pathname,
        search: location.search,
        hash: location.hash,
      },
    });
  }, [location]);

  return <div className="app">{/* Your app content */}</div>;
}

Next.js App Router

jsx
// app/layout.tsx
"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";
// FanFestSDK is available globally after loading the SDK script

export default function RootLayout({ children }) {
  const pathname = usePathname();

  useEffect(() => {
    FanFestSDK.trackEvent({
      action: "page_view",
      description: document.title,
      externalObjectId: pathname,
      metadata: {
        pathname,
        timestamp: new Date().toISOString(),
      },
    });
  }, [pathname]);

  return (
    <html>
      <body>{children}</body>
    </html>
  );
}

Vue.js Integration

vue
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
// FanFestSDK is available globally after loading the SDK script
export default {
  name: "App",
  watch: {
    $route(to, from) {
      // Track page view on route change
      FanFestSDK.trackEvent({
        action: "page_view",
        description: document.title,
        externalObjectId: to.path,
        metadata: {
          from: from.path,
          to: to.path,
          params: to.params,
          query: to.query,
        },
      });
    },
  },
};
</script>

Advanced Patterns

Conditional Page View Tracking

jsx
function ConditionalPageView({ user, page }) {
  useEffect(() => {
    const trackPageView = async () => {
      const baseEvent = {
        action: "page_view",
        description: document.title,
        externalObjectId: page.path,
      };

      if (user.isLoggedIn) {
        await FanFestSDK.trackEvent({
          ...baseEvent,
          metadata: {
            userType: "authenticated",
            userId: user.id,
            pageCategory: page.category,
          },
        });
      } else {
        await FanFestSDK.trackEvent({
          ...baseEvent,
          metadata: {
            userType: "anonymous",
            pageCategory: page.category,
          },
        });
      }
    };

    trackPageView();
  }, [user, page]);

  return <div>{/* Your page content */}</div>;
}

E-commerce Page Tracking

jsx
function ProductPage({ product }) {
  useEffect(() => {
    FanFestSDK.trackEvent({
      action: "page_view",
      description: `Product: ${product.name}`,
      externalObjectId: product.id,
      metadata: {
        pageType: "product",
        productId: product.id,
        category: product.category,
        price: product.price,
        inStock: product.inStock,
      },
    });
  }, [product]);

  return (
    <div>
      <h1>{product.name}</h1>
      <p>${product.price}</p>
      {/* Product content */}
    </div>
  );
}

Blog Post Tracking

jsx
function BlogPost({ post }) {
  useEffect(() => {
    FanFestSDK.trackEvent({
      action: "page_view",
      description: post.title,
      externalObjectId: post.slug,
      metadata: {
        pageType: "blog_post",
        postId: post.id,
        author: post.author,
        publishDate: post.publishDate,
        readTime: post.readTime,
        tags: post.tags,
      },
    });
  }, [post]);

  return (
    <article>
      <h1>{post.title}</h1>
      <p>By {post.author}</p>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  );
}

SSR/CSR Considerations

Avoiding Double Fires

jsx
function PageViewTracker() {
  const [hasTracked, setHasTracked] = useState(false);

  useEffect(() => {
    // Only track on client side
    if (typeof window !== "undefined" && !hasTracked) {
      FanFestSDK.trackEvent({
        action: "page_view",
        description: document.title,
        externalObjectId: window.location.pathname,
      });
      setHasTracked(true);
    }
  }, []);

  return null; // This component doesn't render anything
}

Hydration-Safe Tracking

jsx
function HydrationSafeTracker() {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  useEffect(() => {
    if (isClient) {
      // Track only after hydration
      FanFestSDK.trackEvent({
        action: "page_view",
        description: document.title,
        externalObjectId: window.location.pathname,
      });
    }
  }, [isClient]);

  return null;
}

Performance Optimization

jsx
function OptimizedPageTracker() {
  const [lastTracked, setLastTracked] = useState(null);

  useEffect(() => {
    const currentPath = window.location.pathname;

    // Only track if path has changed
    if (lastTracked !== currentPath) {
      FanFestSDK.trackEvent({
        action: "page_view",
        description: document.title,
        externalObjectId: currentPath,
      });
      setLastTracked(currentPath);
    }
  }, [lastTracked]);

  return null;
}

Error Handling

Network Error Handling

jsx
function RobustPageTracker() {
  useEffect(() => {
    const trackPageView = async () => {
      try {
        await FanFestSDK.trackEvent({
          action: "page_view",
          description: document.title,
          externalObjectId: window.location.pathname,
        });
      } catch (error) {
        console.warn("Failed to track page view:", error);
        // Continue with page load
      }
    };

    trackPageView();
  }, []);

  return null;
}

Retry Logic

jsx
function RetryPageTracker() {
  useEffect(() => {
    const trackWithRetry = async (retries = 3) => {
      try {
        await FanFestSDK.trackEvent({
          action: "page_view",
          description: document.title,
          externalObjectId: window.location.pathname,
        });
      } catch (error) {
        if (retries > 0) {
          // Retry after delay
          setTimeout(() => trackWithRetry(retries - 1), 1000);
        } else {
          console.error("Failed to track page view after retries:", error);
        }
      }
    };

    trackWithRetry();
  }, []);

  return null;
}

Next Steps

Released under the MIT License.