npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@arc-publishing/arctrack

v3.0.0

Published

Library for simply handling application analytics data layer

Downloads

413

Readme

Arctrack

Analytics layer for Arc partner sites built with PageBuilder.

Description

Arctrack is an analytics utility library aimed at simplifying client-side analytics build-outs. It works by seeding an application with different types of action listeners that can respond to general or fine-tuned user actions.

API Overview

trackDom

Takes an options object containing DOM target information and developer-defined (that's you) callbacks that will execute whenever a user action is tracked. trackDom is set up to execute specified callbacks on DOM element click and on scroll.

options

| Key | Data type | required? | default | | ----------| ---------------------| ----------| ---------------- | | dataAttr | string | false | 'data-arctrack'| | click | function | false | undefined | | scroll | array or object | false | undefined |

click

If you've seeded a page with data attributes that match dataAttr, whenever these elements are clicked, your click callback will fire with an object containing the following:

  • target: DOM target element from click event
  • type: a camelcase string derived from the value of the data attribute that observed the click event on the target element.

Example

some serverside page template:

<!-- other HTML or rendering tags -->

<div id="foo" data-sitetrack="social-share">
  <!-- markup... -->
</div>

the application's JS:

import { trackDom } from '@arc-publishing/arctrack';

const options = {
  dataAttr: 'data-sitetrack',
  click: function({ target, type }) {
    console.log('CLICKED!', target, type);
    // use your click data however you need to
    // pass it along to your analytics network call...
  },
  // ...
};

trackDom(options);

in the browser console after a user clicks the 'social share' div:

CLICKED!
div#foo...
socialShare

scroll
An array of scroll entries (objects), or a single scroll entry. Each entry corresponds to a DOM element that should trigger a tracking event when it's scrolled over.

Scroll Entry API .

| Key     | Data type | Required | |----------|-----------|----------| |load | function| true | |buffer | object | false | |selector| string | true | |type | string | true | |trackOnceOnly | bool | false |

load
Developer-defined callback that fires whenever the user scrolls over a page element of this scroll entry type. load is passed an object containing:

  • target: in this case, target is an object containing two properties: node, which is the DOM element that was scrolled over, and data, which is the value assigned to the scroll element's data attribute.
  • type: specified in this entry's type property.

buffer
An object containing properties top and bottom (both JavaScript number), that tells the scroll listener if it should observe a scroll once a buffer (some amount of vertical pixel distance) has been breached either above or below a target element. This can be useful if a tracking event needs to be dispatched when a page element is almost in the viewport.

selector
Should correspond to a data-attribute name on types of elements you would like to have scroll-tracking for. For example, if selector: 'foo', the scroll entry API will search the DOM for elements with a data-foo attribute.

trackOnceOnly
By default, the scroll entry API will continue to fire the load callback every time a registered element is scrolled over. For example, if you've scrolled down over a registered element, it will fire, but if you then scroll back up over it, it will fire again. You can turn this off by setting trackOnceOnly to true.

In the example markup below, your selector would be mysite-leaderboard-ad:

<div data-mysite-leaderboard-ad="1">
  <!-- markup... -->
</div>

type
A name you assign to a particular order of elements on a page. type allows you to track scrolling for a number of different types of elements on a single page. type can often just be the same value as selector, but if you'd like the selector and the element type to be named differently, you have that flexibility.

Complete scrolling example

import { trackDom } from '@arc-publishing/arctrack';

const scrollEntries = [];
scrollEntries.push({
  load: function({ type, target }) {
    if (type === 'ad') {
      // an ad has been scrolled over.
      // collect data from it using target...
      const classes = target.classList;
      // pass along to some analytics library
      s.eVar999 = classes;
      s.tl(undefined, 'o', 'AD_SCROLL');
    }
  },
  buffer: { top: 50, bottom: 50 },
  selector: 'mysite-leaderboard-ad',
  type: 'ad'
});
scrollEntries.push({
  load: function ({ type, target }) {
    /* some logic and custom analytics-gathering for media modules */
  },
  selector: 'video-playlist',
  type: 'media-module',
  trackOnceOnly: true
});
const options = {
  scroll: scrollEntries
};
trackDom(options);

In the example above, elements of type ad have a buffer of 50px, meaning load will fire when the ad element is within 50px of the viewport. media-module entries do not have a buffer.

trackJs

Decorator function used within ES6 classes (including React component classes) that takes a developer-defined callback and executes it whenever a decorated method is fired. This is an efficient way to track user interaction with React or ES6 service-based UIs because tracking transactions take place in memory and require zero interfacing with the DOM. This approach is inspired by New York Times react-tracking library.

trackJs accepts two arguments, a callback (fn) and an event name (string). The callback will be called with an object containing the following data:

TrackJs API .

| Key     | Data type | |----------|------------| |methodName | string| |instance | object | |eventName | string | |args | JavaScript arguments object |

methodName The name of the method that trackJs is decorating.

Example:

import { trackJs } from '@arc-publishing/arctrack';

class MyClass {
  @trackJs(function({ methodName }) {
    console.log(`The method name is ${methodName}.`);
  })
  baz() {
    console.log('Hello, world!');
  }
}

When baz is called, the trackJs callback function above would print:

The method name is baz.

instance

The instance is the this value of the class instance in which you are decorating. This is very useful in cases where you're tracking React component behavior, because you'll have access to state and props by way of instance.

Example:

import React, { Component } from 'react';
import { trackJs } from '@arc-publishing/arctrack';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      active: false
    }
  }
  @trackJs(function({ instance }) {
    const { state } = instance;
    if (state.active) {
      // do something ... 
    }
  })
  handleClick(e) {
    this.setState({
      active: !this.state.active
    });
  }
  render() {
    return (
      <div onClick={this.handleClick}>
        {/* ... */}
      </div>
    );
  }
}

eventName

A string passed as the second argument to trackJs, to be used by the callback to further categorize the type of behavior being tracked.

Example:

import React, { Component } from 'react';
import { trackJs } from '@arc-publishing/arctrack';
import { trackClicks } from '../analytics';

class Menu extends Component {
  constructor(props) {
    super(props);
    this.state = {
      active: false
    }
  }
  @trackJs(trackClicks, 'OPEN_MENU')
  handleClick(e) {
    this.setState({
      active: !this.state.active
    });
  }
  render() {
    return (
      <div onClick={this.handleClick}>
        {/* ... */}
      </div>
    );
  }

analytics/index.js

export const trackClicks = function({ instance, eventName }) {
  if (eventName === 'OPEN_MENU') {
    if (instance.state && !instance.state.active) {
      s.tl(undefined, 'o', 'OPEN_MENU');
    }
  }
  // ... 
}

In the example above, active would be false if the component were clicked to be opened, since the trackJs callback fires before the method code itself runs, setting state to {active: true}. Using eventName allows you as the developer to combine multiple event types into a single callback, such as trackClicks, which could track different types of click events differently depending on the eventName value, but reuse a lot of code as well.

args

These are the arguments passed to the method you are decorating. For React onClick handlers, this parameter could give you access to the click target, for very refined observation and tracking.

Example:

import React, { Component } from 'react';
import { trackJs } from '@arc-publishing/arctrack';

class Comments extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showComments: props.loggedIn ? false : true,
    };
    // ...
  }
  // ...
  @trackJs(function({ args }) {
    if (args.length > 0) {
      const [syntheticEvent] = args;
      console.log('target', syntheticEvent.target);
    }
  })
  toggleShowComments(e) {
    this.setState({ showComments: !this.state.showComments });
  }
  
  render() {
    return (
      <div>
        <button onClick={this.toggleShowComments}>
          {/* ... */}
        </button>
        {this.state.showComments && (
          <Fragment>
            {/* ... */}
          </Fragment>
        )}
      </div>
    );
  }
}

Example Usage