0.3.3 • Published 2 months ago

@analytics/snowplow v0.3.3

Weekly downloads
3,444
License
MIT
Repository
github
Last release
2 months ago

Snowplow plugin for analytics

Integration with Snowplow Analytics for analytics package.

View the docs

Installation

Install analytics and @analytics/snowplow packages

npm install analytics
npm install @analytics/snowplow

How to use

The @analytics/snowplow package works in the browser and server-side in Node.js. To use, install the package, include in your project and initialize the plugin with analytics.

Below is an example of how to use the browser plugin.

import Analytics from 'analytics'
import snowplowPlugin from '@analytics/snowplow'

const analytics = Analytics({
  app: 'awesome-app',
  plugins: [
    // Minimal recommended configuration
    snowplowPlugin({
      name: 'snowplow',
      collectorUrl: 'collector.mysite.com',
      trackerSettings: {
        appId: 'myApp'
      }
    })
  ]
})

/* Track a page view */
// Enable some automatic tracking before page event
analytics.on('initialize:snowplow', ({ instance }) => {
  instance.plugins.snowplow.enableActivityTracking(10, 10)
  instance.plugins.snowplow.enableLinkClickTracking()
})

// Track page
analytics.page()

// or Track page view with additional entities
analytics.page({
  contexts: [
    {
      schema: 'iglu:com.acme/blog_post/jsonschema/1-0-0',
      data: {
        title: 'Re-thinking the structure of event data',
        category: 'Data Insights',
        author: 'Cara Baestlein',
        datePublished: '2020-01-24'
      }
    }
  ]
})

/* Track a custom event */
// Track structured event
analytics.track('playedVideo', {
  category: 'Videos',
  label: 'Fall Campaign',
  value: 42
})

// or Track Self Describing event
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign'
  }
})

// or Track Self Describing event with additional entities
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign',
    videoTimestampInMs: 1104
  },
  contexts: [
    {
      schema: 'iglu:com.acme/product/jsonschema/1-0-0',
      data: {
        id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
        category: 'clothing',
        subCategory: 'socks',
        price: 3.99
      }
    }
  ]
})

// or Track Enchanced Ecommerce event with product context
analytics.track('EnhancedEcommerceProductContext', {
  id: 'P12345',
  name: 'Android Warhol T-Shirt',
  list: 'Search Results',
  brand: 'Google',
  category: 'Apparel/T-Shirts',
  variant: 'Black',
  quantity: 1
})
analytics.track('EnhancedEcommerceAction', {
  action: 'add'
})

/* Identify a visitor */
analytics.identify('user-id-xyz')

After initializing analytics with the snowplowPlugin plugin, data will be sent into Snowplow Analytics whenever analytics.page, analytics.track, or analytics.identify are called.

See additional implementation examples for more details on using in your project.

Platforms Supported

The @analytics/snowplow package works in the browser and server-side in Node.js

Browser usage

The Snowplow Analytics client side browser plugin works with these analytic api methods:

Browser API

import Analytics from 'analytics'
import snowplowPlugin from '@analytics/snowplow'

const analytics = Analytics({
  app: 'awesome-app',
  plugins: [
    // Minimal recommended configuration
    snowplowPlugin({
      name: 'snowplow',
      collectorUrl: 'collector.mysite.com',
      trackerSettings: {
        appId: 'myApp'
      }
    })
  ]
})

Configuration options for browser

Optiondescription
collectorUrl required - stringThe URL to a Snowplow collector
name optional - stringThe name to identify this instance of the tracker, use if using multiple tracker instances ('snowplow' default)
trackerSettings optional - ObjectThe arg map to pass to the Snowplow Tracker
trackerSettings.appId optional - stringThe appId to identify this application
trackerSettings.platform optional - stringPlatform of tracking ("web" default)
trackerSettings.cookieDomain optional - stringDomain to set cookie against
trackerSettings.discoverRootDomain optional - stringAutomatically discover root domain
trackerSettings.cookieName optional - stringPrefix for cookies ("sp" default)
trackerSettings.cookieSameSite optional - stringSameSite cookie setting ("None" default)
trackerSettings.cookieSecure optional - booleanSecure cookie setting (true default)
trackerSettings.encodeBase64 optional - booleanEncode JSON objects as Base64 (true default)
trackerSettings.respectDoNotTrack optional - boleanRespect do not track (consider analytics-plugin-do-not-track) (false default)
trackerSettings.eventMethod optional - stringMethod to send events, GET, POST, Beacon (POST default)
trackerSettings.bufferSize optional - numberAmount of events to buffer before sending (1 default)
trackerSettings.maxPostBytes optional - numberMaximum size of POST or Beacon before sending (40000 default)
trackerSettings.crossDomainLinker optional - stringfunction to configure which links to add cross domain linking
trackerSettings.cookieLifetime optional - numberCookie lifetime (63072000 default)
trackerSettings.stateStorageStrategy optional - stringUse cookies and/or localstorage ("cookieAndLocalStorage" default)
trackerSettings.maxLocalStorageQueueSize optional - numberMaximum numbers of events to buffer in localstorage to prevent filling local storage (1000 default)
trackerSettings.resetActivityTrackingOnPageView optional - booleanFlag to decide whether to reset page ping timers on virtual page view (true default)
trackerSettings.connectionTimeout optional - booleanThe timeout, in milliseconds, before GET and POST requests will timeout (5000 default) (Snowplow JS 2.15.0+)
trackerSettings.anonymousTracking optional - ObjectFlag to enable anonymous tracking functionality (false default)
trackerSettings.anonymousTracking.withSessionTracking optional - booleanFlag to enable whether to continue tracking sessions in anonymous tracking mode (false default)
trackerSettings.anonymousTracking.withServerAnonymisation optional - booleanFlag which prevents collector from returning and capturing cookies and capturing ip address (false default)
trackerSettings.contexts optional - ObjectThe auto contexts for each event
trackerSettings.contexts.webPage optional - booleanThe webpage context, containing the page view id. (true default)
trackerSettings.contexts.performanceTiming optional - booleanAdd performance timing information
trackerSettings.contexts.clientHints optional - ObjectAdd Client Hint information (Snowplow JS 2.15.0+)
trackerSettings.contexts.clientHints.includeHighEntropy optional - booleanCapture High Entropy Client Hints (Snowplow JS 2.15.0+)
trackerSettings.contexts.gaCookies optional - booleanAdd gaCookie information
trackerSettings.contexts.geolocation optional - booleanAdd browser geolocation information
trackerSettings.contexts.optimizelyXSummary optional - booleanAdd browser geolocation information
trackerSettings.plugins optional - ArrayAdditional plugins to include at tracker initialisation. See https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/browser-tracker/browser-tracker-v3-reference/plugins/

Server-side usage

The Snowplow Analytics server-side node.js plugin works with these analytic api methods:

Server-side API

import Analytics from 'analytics'
import snowplowPlugin from '@analytics/snowplow'

const analytics = Analytics({
  app: 'awesome-app',
  plugins: [
    snowplowPlugin({
      name: 'snowplow',
      collectorUrl: 'collector.mysite.com',
      appId: 'myApp'
    })
  ]
})

Configuration options for server-side

Optiondescription
collectorUrl required - stringThe URL to a Snowplow collector
appId required - stringThe appId to identify this application
name optional - stringThe name to identify this instance of the tracker ('snowplow' default)
protocol optional - string'http' or 'https' ('https' default)
port optional - stringcollector port (80 or 443 default)
method optional - stringThe method to send events to collector, 'post' or 'get' ('post' default)
bufferSize optional - stringOnly send events once n are buffered. Defaults to 1 for GET requests and 10 for POST requests.
retries optional - stringThe number of times the tracker will try to resend an event. Defaults to 5.
maxSockets optional - stringNode.js agentOptions object to tune performance (6 default)
platform optional - stringSets the platform https://bit.ly/302dSQy ('srv' default)
screenResolution optional - objectSets device screen resolution if available
screenResolution.width optional - numberPositive Integer for screen width
screenResolution.height optional - numberPositive Integer for screen height
viewport optional - objectSets device viewport if available
viewport.width optional - numberPositive Integer for viewport width
viewport.height optional - numberPositive Integer for viewprt height
colorDepth optional - numberPositive Integer, in bits per pixel
timezone optional - stringSet user’s timezone e.g. 'Europe/London'
lang optional - stringSer user's lang e.globalThis. 'en'

Additional examples

Below are additional implementation examples.

import Analytics from 'analytics'
import snowplowPlugin from '@analytics/snowplow'

const analytics = Analytics({
  app: 'awesome-app',
  plugins: [
    snowplowPlugin({
      name: 'snowplow',
      collectorUrl: 'collector.mysite.com',
      appId: 'myApp'
    })
    // ...other plugins
  ]
})

/* Track a page view */
// Track page
analytics.page()

// or Track page view with additional entities
analytics.page({
  contexts: [
    {
      schema: 'iglu:com.acme/blog_post/jsonschema/1-0-0',
      data: {
        title: 'Re-thinking the structure of event data',
        url:
          'https://snowplowanalytics.com/blog/2020/01/24/re-thinking-the-structure-of-event-data/',
        category: 'Data Insights',
        author: 'Cara Baestlein',
        datePublished: '2020-01-24'
      }
    }
  ]
})

/* Track a custom event */
// Track structured event
analytics.track('playedVideo', {
  category: 'Videos',
  label: 'Fall Campaign',
  value: 42
})

// or Track Self Describing event
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign'
  }
})

// or Track Self Describing event with additional entities
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign',
    videoTimestampInMs: 1104
  },
  contexts: [
    {
      schema: 'iglu:com.acme/product/jsonschema/1-0-0',
      data: {
        id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
        category: 'clothing',
        subCategory: 'socks',
        price: 3.99
      }
    }
  ]
})

// or Track Enchanced Ecommerce event with product context
analytics.track('ScreenView', {
  name: 'Product Page',
  id: 'p-123',
  contexts: [
    {
      schema: 'iglu:com.acme/product/jsonschema/1-0-0',
      data: {
        id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
        category: 'clothing',
        subCategory: 'socks',
        price: 3.99
      }
    }
  ]
})

/* Identify a visitor */
analytics.identify('user-id-xyz', {
  firstName: 'bill',
  lastName: 'murray'
})

If using node, you will want to import the .default

const analyticsLib = require('analytics').default
const snowplowPlugin = require('@analytics/snowplow').default

const analytics = analyticsLib({
  app: 'my-app-name',
  plugins: [
    snowplowPlugin({
      name: 'snowplow',
      collectorUrl: 'collector.mysite.com',
      appId: 'myApp'
    })
  ]
})

/* Track a page view */
// Track page
analytics.page()

// or Track page view with additional entities
analytics.page({
  contexts: [
    {
      schema: 'iglu:com.acme/blog_post/jsonschema/1-0-0',
      data: {
        title: 'Re-thinking the structure of event data',
        url:
          'https://snowplowanalytics.com/blog/2020/01/24/re-thinking-the-structure-of-event-data/',
        category: 'Data Insights',
        author: 'Cara Baestlein',
        datePublished: '2020-01-24'
      }
    }
  ]
})

/* Track a custom event */
// Track structured event
analytics.track('playedVideo', {
  category: 'Videos',
  label: 'Fall Campaign',
  value: 42
})

// or Track Self Describing event
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign'
  }
})

// or Track Self Describing event with additional entities
analytics.track('selfDescribingEvent', {
  schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
  data: {
    id: 42,
    title: 'Fall Campaign',
    videoTimestampInMs: 1104
  },
  contexts: [
    {
      schema: 'iglu:com.acme/product/jsonschema/1-0-0',
      data: {
        id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
        category: 'clothing',
        subCategory: 'socks',
        price: 3.99
      }
    }
  ]
})

// or Track Enchanced Ecommerce event with product context
analytics.track('ScreenView', {
  name: 'Product Page',
  id: 'p-123',
  contexts: [
    {
      schema: 'iglu:com.acme/product/jsonschema/1-0-0',
      data: {
        id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
        category: 'clothing',
        subCategory: 'socks',
        price: 3.99
      }
    }
  ]
})

/* Identify a visitor */
analytics.identify('user-id-xyz', {
  firstName: 'bill',
  lastName: 'murray'
})

Below is an example of importing via the unpkg CDN. Please note this will pull in the latest version of the package.

<!DOCTYPE html>
<html>
  <head>
    <title>Using @analytics/snowplow in HTML</title>
    <script src="https://unpkg.com/analytics/dist/analytics.min.js"></script>
    <script src="https://unpkg.com/@analytics/snowplow/dist/@analytics/snowplow.min.js"></script>
    <script type="text/javascript">
      /* Initialize analytics */
      var Analytics = _analytics.init({
        app: 'my-app-name',
        plugins: [
          // Minimal recommended configuration
          analyticsSnowplow({
            name: 'snowplow',
            collectorUrl: 'collector.mysite.com',
            trackerSettings: {
              appId: 'myApp'
            }
          })
        ]
      })

      /* Track a page view */
      // Enable some automatic tracking before page event
      analytics.on('initialize:snowplow', ({ instance }) => {
        instance.plugins.snowplow.enableActivityTracking(10, 10)
        instance.plugins.snowplow.enableLinkClickTracking()
      })

      // Track page
      analytics.page()

      // or Track page view with additional entities
      analytics.page({
        contexts: [
          {
            schema: 'iglu:com.acme/blog_post/jsonschema/1-0-0',
            data: {
              title: 'Re-thinking the structure of event data',
              category: 'Data Insights',
              author: 'Cara Baestlein',
              datePublished: '2020-01-24'
            }
          }
        ]
      })

      /* Track a custom event */
      // Track structured event
      analytics.track('playedVideo', {
        category: 'Videos',
        label: 'Fall Campaign',
        value: 42
      })

      // or Track Self Describing event
      analytics.track('selfDescribingEvent', {
        schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
        data: {
          id: 42,
          title: 'Fall Campaign'
        }
      })

      // or Track Self Describing event with additional entities
      analytics.track('selfDescribingEvent', {
        schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
        data: {
          id: 42,
          title: 'Fall Campaign',
          videoTimestampInMs: 1104
        },
        contexts: [
          {
            schema: 'iglu:com.acme/product/jsonschema/1-0-0',
            data: {
              id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
              category: 'clothing',
              subCategory: 'socks',
              price: 3.99
            }
          }
        ]
      })

      // or Track Enchanced Ecommerce event with product context
      analytics.track('EnhancedEcommerceProductContext', {
        id: 'P12345',
        name: 'Android Warhol T-Shirt',
        list: 'Search Results',
        brand: 'Google',
        category: 'Apparel/T-Shirts',
        variant: 'Black',
        quantity: 1
      })
      analytics.track('EnhancedEcommerceAction', {
        action: 'add'
      })

      /* Identify a visitor */
      analytics.identify('user-id-xyz')
    </script>
  </head>
  <body>
    ....
  </body>
</html>

Using @analytics/snowplow in ESM modules.

<!DOCTYPE html>
<html>
  <head>
    <title>Using @analytics/snowplow in HTML via ESModules</title>
    <script>
      // Polyfill process.
      // **Note**: Because `import`s are hoisted, we need a separate, prior <script> block.
      window.process = window.process || { env: { NODE_ENV: 'production' } }
    </script>
    <script type="module">
      import analytics from 'https://unpkg.com/analytics/lib/analytics.browser.es.js?module'
      import analyticsSnowplow from 'https://unpkg.com/@analytics/snowplow/lib/analytics-plugin-snowplow.browser.es.js?module'
      /* Initialize analytics */
      const Analytics = analytics({
        app: 'analytics-html-demo',
        debug: true,
        plugins: [
          // Minimal recommended configuration
          analyticsSnowplow({
            name: 'snowplow',
            collectorUrl: 'collector.mysite.com',
            trackerSettings: {
              appId: 'myApp'
            }
          })
          // ... add any other third party analytics plugins
        ]
      })

      /* Track a page view */
      // Enable some automatic tracking before page event
      analytics.on('initialize:snowplow', ({ instance }) => {
        instance.plugins.snowplow.enableActivityTracking(10, 10)
        instance.plugins.snowplow.enableLinkClickTracking()
      })

      // Track page
      analytics.page()

      // or Track page view with additional entities
      analytics.page({
        contexts: [
          {
            schema: 'iglu:com.acme/blog_post/jsonschema/1-0-0',
            data: {
              title: 'Re-thinking the structure of event data',
              category: 'Data Insights',
              author: 'Cara Baestlein',
              datePublished: '2020-01-24'
            }
          }
        ]
      })

      /* Track a custom event */
      // Track structured event
      analytics.track('playedVideo', {
        category: 'Videos',
        label: 'Fall Campaign',
        value: 42
      })

      // or Track Self Describing event
      analytics.track('selfDescribingEvent', {
        schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
        data: {
          id: 42,
          title: 'Fall Campaign'
        }
      })

      // or Track Self Describing event with additional entities
      analytics.track('selfDescribingEvent', {
        schema: 'iglu:com.acme/video_played/jsonschema/1-0-0',
        data: {
          id: 42,
          title: 'Fall Campaign',
          videoTimestampInMs: 1104
        },
        contexts: [
          {
            schema: 'iglu:com.acme/product/jsonschema/1-0-0',
            data: {
              id: 'f9cb6cb6-5ca8-47a6-9035-d9c6ac13029e',
              category: 'clothing',
              subCategory: 'socks',
              price: 3.99
            }
          }
        ]
      })

      // or Track Enchanced Ecommerce event with product context
      analytics.track('EnhancedEcommerceProductContext', {
        id: 'P12345',
        name: 'Android Warhol T-Shirt',
        list: 'Search Results',
        brand: 'Google',
        category: 'Apparel/T-Shirts',
        variant: 'Black',
        quantity: 1
      })
      analytics.track('EnhancedEcommerceAction', {
        action: 'add'
      })

      /* Identify a visitor */
      analytics.identify('user-id-xyz')
    </script>
  </head>
  <body>
    ....
  </body>
</html>

See the full list of analytics provider plugins in the main repo.