Chartbeat Install / Embed Tag or SDK | OpsBlu Docs

Chartbeat Install / Embed Tag or SDK

Deployment approach for installing Chartbeat's tag or SDK across web, mobile, and server environments.

Overview

Chartbeat offers multiple deployment methods to accommodate different technical architectures and publishing platforms. The choice of implementation method depends on your CMS, development workflow, consent management requirements, and technical capabilities. This guide covers all major deployment approaches with detailed code examples and best practices.

Deployment Decision Matrix

Method Best For Pros Cons
Tag Manager Most organizations with GTM/Tealium Easy updates, no code deploys TMS dependency, slight delay
CMS Template WordPress, Drupal, custom CMS Fast loading, reliable Requires CMS updates
Hard-Coded Static sites, simple setups Maximum control, fastest Manual updates needed
Mobile SDK Native iOS/Android apps Native performance, offline support Separate implementation
Server-Side AMP, SSR frameworks SEO benefits, bot filtering Limited engagement tracking

Deployment Strategy

Primary Deployment Method Selection

Recommended Approach: Tag Manager Integration

  • Inject Chartbeat via Google Tag Manager, Tealium, or Adobe Launch
  • Populate configuration from data layer variables
  • Enable dynamic metadata updates without code deployments
  • Centralize consent management and script sequencing
  • Simplify cross-team collaboration (marketing, analytics, engineering)

Alternative: CMS Template Integration

  • Embed directly in CMS templates (WordPress, Drupal, custom platforms)
  • Ensure script loads after consent if required
  • Leverage CMS metadata for automatic population of sections, authors, titles
  • Ideal when tag manager adds unacceptable latency
  • Provides maximum performance and reliability

When to Use Hard-Coded Implementation

  • Static sites or simple HTML deployments
  • Maximum performance requirements
  • No tag manager or CMS infrastructure
  • Full developer control over script loading and configuration

Key Implementation Considerations

Consent Management

  • Load Chartbeat only after user consent in GDPR/CCPA jurisdictions
  • Gate heartbeat pings until opt-in is confirmed
  • Implement cookie-less tracking if required (noCookies: true)
  • Coordinate with OneTrust, Cookiebot, or custom consent solutions

Script Loading Sequence

  • Load Chartbeat early for accurate engagement timing
  • Ensure it fires after consent but before user interaction
  • Avoid race conditions with other analytics tools
  • Prevent multiple script inclusions on the same page

Heartbeat Configuration

  • Default interval: 15 seconds (recommended by Chartbeat)
  • Adjust for SPA frameworks to maintain timers across route changes
  • Consider network conditions for mobile users
  • Monitor ping frequency to avoid excessive API calls

Tag Manager Deployment

Google Tag Manager Implementation

Step 1: Create Data Layer Variables

Create these variables in GTM to populate Chartbeat configuration:

Variable Name Type Data Layer Variable Example Value
chartbeat.uid Data Layer Variable chartbeat_uid 12345
chartbeat.domain Data Layer Variable chartbeat_domain example.com
chartbeat.sections Data Layer Variable chartbeat_sections News,Politics
chartbeat.authors Data Layer Variable chartbeat_authors Jane Smith
chartbeat.title Data Layer Variable page_title Article Title
chartbeat.path Data Layer Variable page_path /news/politics/article

Step 2: Configure Custom HTML Tag

Create a Custom HTML tag with this configuration:

<script type="text/javascript">
  var _sf_async_config = {
    uid: {{chartbeat.uid}},
    domain: '{{chartbeat.domain}}',
    useCanonical: true,
    useCanonicalDomain: true,
    sections: '{{chartbeat.sections}}',
    authors: '{{chartbeat.authors}}',
    title: '{{chartbeat.title}}',
    path: '{{chartbeat.path}}'
  };

  (function() {
    function loadChartbeat() {
      var e = document.createElement('script');
      var n = document.getElementsByTagName('script')[0];
      e.type = 'text/javascript';
      e.async = true;
      e.src = '//static.chartbeat.com/js/chartbeat.js';
      n.parentNode.insertBefore(e, n);
    }
    loadChartbeat();
  })();
</script>

Step 3: Set Trigger Conditions

  • Trigger Type: Page View - DOM Ready
  • Fire On: All Pages (or specific page types)
  • Exceptions: Add consent-related conditions if needed

Step 4: Set Tag Sequencing

  • Fire After: Consent management tag completes
  • Fire Before: Other analytics tags that depend on Chartbeat
  • Priority: Set to higher priority than general analytics tags

Step 5: SPA Virtual Page View Configuration

For single-page applications, create an additional Custom HTML tag:

<script type="text/javascript">
  (function() {
    // Wait for pSUPERFLY to be available
    var checkChartbeat = setInterval(function() {
      if (typeof pSUPERFLY !== 'undefined') {
        clearInterval(checkChartbeat);

        // Update configuration with new page data
        _sf_async_config.sections = '{{chartbeat.sections}}';
        _sf_async_config.authors = '{{chartbeat.authors}}';
        _sf_async_config.title = '{{chartbeat.title}}';
        _sf_async_config.path = '{{chartbeat.path}}';

        // Trigger virtual page view
        pSUPERFLY.virtualPage({
          sections: '{{chartbeat.sections}}',
          authors: '{{chartbeat.authors}}',
          title: '{{chartbeat.title}}',
          path: '{{chartbeat.path}}'
        });
      }
    }, 100);
  })();
</script>
  • Trigger Type: Custom Event - virtualPageview (or your SPA route change event)
  • Fire On: Route change events from your SPA framework

Tealium iQ Implementation

Load Rule Configuration

// Tealium utag.js extension
if (typeof _sf_async_config === 'undefined') {
  var _sf_async_config = {};
}

_sf_async_config.uid = utag_data.chartbeat_uid || 12345;
_sf_async_config.domain = utag_data.chartbeat_domain || 'example.com';
_sf_async_config.sections = utag_data.chartbeat_sections || '';
_sf_async_config.authors = utag_data.chartbeat_authors || '';
_sf_async_config.title = utag_data.page_title || document.title;
_sf_async_config.path = utag_data.page_path || window.location.pathname;
_sf_async_config.useCanonical = true;

(function() {
  var e = document.createElement('script');
  e.async = true;
  e.src = '//static.chartbeat.com/js/chartbeat.js';
  document.body.appendChild(e);
})();

Direct Embed or Hard-Coded Scripts

Standard Implementation

Place this code in your HTML template, ideally near the end of the <body> tag:

<!DOCTYPE html>
<html>
<head>
  <title>Your Page Title</title>
</head>
<body>
  <!-- Your page content -->

  <!-- Chartbeat Configuration -->
  <script type="text/javascript">
    var _sf_async_config = {
      uid: 12345,                              // Required: Your Chartbeat UID
      domain: 'example.com',                   // Required: Your domain
      useCanonical: true,                      // Recommended: Use canonical URL
      useCanonicalDomain: true,                // Recommended: Use canonical domain
      sections: 'News,Politics',               // Section taxonomy
      authors: 'Jane Smith',                   // Author attribution
      title: 'Article Headline Goes Here',    // Page title
      path: '/news/politics/article-slug',    // Canonical path

      // Optional configuration
      noCookies: false,                        // Set to true for cookie-less tracking
      flickerControl: false,                   // A/B test flicker control
      mabAllow: true                          // Enable headline testing
    };
  </script>

  <!-- Chartbeat Script Loader -->
  <script type="text/javascript">
    (function() {
      function loadChartbeat() {
        window._sf_endpt = (new Date()).getTime();
        var e = document.createElement('script');
        var n = document.getElementsByTagName('script')[0];
        e.type = 'text/javascript';
        e.async = true;
        e.src = '//static.chartbeat.com/js/chartbeat.js';
        n.parentNode.insertBefore(e, n);
      }

      if (window.addEventListener) {
        window.addEventListener('load', loadChartbeat, false);
      } else if (window.attachEvent) {
        window.attachEvent('onload', loadChartbeat);
      } else {
        loadChartbeat();
      }
    })();
  </script>
</body>
</html>

CMS-Specific Examples

WordPress Implementation

Add to your theme's footer.php or use a plugin like Insert Headers and Footers:

<!-- Chartbeat Analytics -->
<script type="text/javascript">
  var _sf_async_config = {
    uid: <?php echo get_option('chartbeat_uid', 12345); ?>,
    domain: '<?php echo $_SERVER['HTTP_HOST']; ?>',
    useCanonical: true,
    useCanonicalDomain: true,
    sections: '<?php echo get_the_category()[0]->name; ?>',
    authors: '<?php echo get_the_author(); ?>',
    title: '<?php echo get_the_title(); ?>',
    path: '<?php echo parse_url(get_permalink(), PHP_URL_PATH); ?>'
  };
</script>
<script type="text/javascript" src="//static.chartbeat.com/js/chartbeat.js"></script>

React/Next.js Implementation

Create a Chartbeat component:

// components/Chartbeat.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';

const Chartbeat = ({ uid, domain, sections, authors, title }) => {
  const router = useRouter();

  useEffect(() => {
    // Initialize Chartbeat
    window._sf_async_config = {
      uid: uid,
      domain: domain,
      useCanonical: true,
      useCanonicalDomain: true,
      sections: sections,
      authors: authors,
      title: title,
      path: router.asPath
    };

    // Load script
    const script = document.createElement('script');
    script.src = '//static.chartbeat.com/js/chartbeat.js';
    script.async = true;
    document.body.appendChild(script);

    // Handle route changes
    const handleRouteChange = (url) => {
      if (typeof window.pSUPERFLY !== 'undefined') {
        window.pSUPERFLY.virtualPage({
          sections: sections,
          authors: authors,
          title: document.title,
          path: url
        });
      }
    };

    router.events.on('routeChangeComplete', handleRouteChange);

    return () => {
      router.events.off('routeChangeComplete', handleRouteChange);
    };
  }, [router, uid, domain, sections, authors, title]);

  return null;
};

export default Chartbeat;

Mobile & OTT SDKs

iOS SDK Implementation

Installation via CocoaPods

# Podfile
pod 'Chartbeat', '~> 5.0'

Swift Configuration

import Chartbeat

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Initialize Chartbeat
        Chartbeat.sharedTracker().startTracker(
            withAccountId: "12345",
            domain: "example.com"
        )

        return true
    }
}

// Track page views
Chartbeat.sharedTracker().trackView(
    viewId: "article-123",
    viewTitle: "Article Headline",
    authors: ["Jane Smith"],
    sections: ["News", "Politics"]
)

Android SDK Implementation

Gradle Dependency

dependencies {
    implementation 'com.chartbeat:chartbeat-android:5.0.0'
}

Kotlin Configuration

import com.chartbeat.androidsdk.Tracker

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Initialize Chartbeat
        val tracker = Tracker.getInstance()
        tracker.setAccountId("12345")
        tracker.setDomain("example.com")
        tracker.startTracker(this)

        // Track page view
        tracker.trackView(
            viewId = "article-123",
            title = "Article Headline",
            authors = listOf("Jane Smith"),
            sections = listOf("News", "Politics")
        )
    }
}

WebView Integration

For hybrid apps using WebViews, inject the standard JavaScript implementation:

// Inject into WebView
String chartbeatScript =
    "var _sf_async_config = {" +
    "  uid: 12345," +
    "  domain: 'example.com'," +
    "  sections: 'News,Politics'," +
    "  authors: 'Jane Smith'" +
    "};" +
    "(function(){" +
    "  var e = document.createElement('script');" +
    "  e.src = '//static.chartbeat.com/js/chartbeat.js';" +
    "  e.async = true;" +
    "  document.body.appendChild(e);" +
    "})();";

webView.evaluateJavascript(chartbeatScript, null);

Server-Side Collection

AMP (Accelerated Mobile Pages)

AMP pages require a special analytics configuration:

<amp-analytics type="chartbeat">
  <script type="application/json">
  {
    "vars": {
      "uid": "12345",
      "domain": "example.com",
      "sections": "News,Politics",
      "authors": "Jane Smith",
      "title": "Article Headline"
    }
  }
  </script>
</amp-analytics>

Server-Side Rendering (SSR)

For Next.js, Nuxt, or other SSR frameworks, generate the config server-side:

// pages/_document.js (Next.js)
import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    const { pageProps } = this.props.__NEXT_DATA__.props;

    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />

          <script
            dangerouslySetInnerHTML={{
              __html: `
                var _sf_async_config = {
                  uid: 12345,
                  domain: 'example.com',
                  sections: '${pageProps.sections || ''}',
                  authors: '${pageProps.authors || ''}',
                  title: '${pageProps.title || ''}',
                  path: '${pageProps.path || ''}'
                };
              `
            }}
          />
          <script async src="//static.chartbeat.com/js/chartbeat.js" />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Validation Checklist

Pre-Deployment Validation

  • UID and domain configured correctly
  • Script loads asynchronously without blocking page render
  • Configuration variables populated from correct data sources
  • Consent management integration working properly
  • No JavaScript errors in browser console
  • Script loads from Chartbeat CDN successfully

Post-Deployment Validation

Real-Time Dashboard Checks

  • Concurrent user count shows test traffic
  • Engagement timer increments properly
  • Section and author metadata appears correctly
  • Page titles and paths match expected values
  • Geographic data shows correct location

Network Analysis

  • Initial ping sends complete configuration
  • Heartbeat pings occur at 15-second intervals
  • Payload size is reasonable (< 2KB per ping)
  • No duplicate pings or infinite loops
  • Proper HTTP status codes (200 OK)

Cross-Browser Testing

  • Chrome (latest and previous version)
  • Firefox (latest and previous version)
  • Safari (latest and previous version)
  • Edge (latest version)
  • Mobile browsers (iOS Safari, Android Chrome)

SPA-Specific Validation (if applicable)

  • Virtual page views fire on route changes
  • Metadata updates with new page context
  • Engagement timer continues (doesn't reset)
  • No duplicate tracker initialization
  • Browser back/forward navigation works correctly

Performance Validation

Metric Target How to Measure
Script load time < 500ms Network tab in DevTools
Time to first ping < 2s Network tab in DevTools
Page load impact < 100ms Lighthouse performance audit
Heartbeat interval 15s ± 1s Monitor ping timing in Network tab
Payload size < 2KB Network tab, ping request size

Troubleshooting Common Issues

Issue Symptoms Diagnosis Resolution
Script not loading No network requests to chartbeat.com Check browser console for errors Verify script URL, check CSP policies, ensure no ad blockers
Missing configuration Pings missing metadata fields Inspect _sf_async_config in console Check data layer values, verify variable mapping
Duplicate tracking Multiple pings per heartbeat interval Check for duplicate script includes Remove redundant implementations, check TMS tag firing
Consent blocking No pings before consent Expected behavior in GDPR regions Verify consent integration, check for errors in consent callback
SPA tracking broken No virtual page views on navigation Monitor pSUPERFLY object availability Implement virtualPage calls, check router integration
Performance impact Slow page loads Run Lighthouse audit Verify async loading, check ping frequency, optimize payload
Mobile SDK errors Crashes or missing data Check device logs Verify SDK version compatibility, check initialization
Cross-domain issues Referrer data incorrect Check referrer values in pings Implement proper referrer passing, check redirect chains

Configuration Recommendations

SPA Integration: Use Chartbeat's pSUB() function to send virtual pageviews on route changes. Call pSUB({sections: 'new-section', authors: 'Author Name', path: '/new-path', title: 'New Title'}) after each navigation. Engagement timers reset automatically on pSUB() calls.

Heartbeat Interval: Keep the default 15-second heartbeat interval unless you have a specific reason to change it. Shorter intervals increase network requests; longer intervals reduce engagement accuracy. The 15-second default balances data granularity with performance.

Feature Enablement: Enable headline testing (mabAllow: true in config) if your editorial team wants A/B test headlines — Chartbeat will automatically rotate headlines and measure engagement. Enable the recirculation module only if you use Chartbeat's content recommendation widget. Video tracking requires the Video module and a compatible player (JW Player, Brightcove, or HTML5 <video>).

Best Practices

  1. Load Early, Load Async: Place Chartbeat high in the page but always load asynchronously
  2. Validate Metadata: Ensure sections, authors, and titles are accurate and consistent
  3. Monitor Performance: Regularly audit script impact on page load times
  4. Test Thoroughly: Validate across browsers, devices, and network conditions
  5. Plan for Consent: Always respect user privacy and comply with regional regulations
  6. Version Control: Track changes to implementation and configuration
  7. Monitor Data Quality: Regularly audit Real-Time dashboard for anomalies