@aller/blink
TypeScript icon, indicating that this package has built-in type declarations

8.26.2 • Public • Published

blink

Library for user behaviour tracking.

Goals

The main goal is to make it easy to track user behavior on our sites.

  • easy to configure
  • fast
  • small bundle size
  • only collects and stores what is necessary
  • ability to track multiple pages at the same time

Trackers

We have several types of trackers:

  • Pageload tracking
  • Active time tracking
  • Impression tracking
  • Ad tracking
  • Click tracking
  • Video tracking
  • TCF consent change tracking
  • Chrome Web Vitals tracking

In addition, we expose one custom tracker type to fill miscellaneous needs.

Usage

import createBlink from '@aller/blink';

const blink = createBlink({
  send: events => console.log(events), // Specify how to send events. events,
  sendDirect: events => console.log(events), // Specify how to send events directly (without checking for duplicates, batching or waiting)
  useDevTools: true, // redux devtools enabled
});

// Initialize a new "page",
// flushes state, and creates a new uuid for the pageView
blink.pageInit({
  abCookie: 51,
  commercialSegments: 'sport,soccer,gardening',
  pageId: 'front-page',
  pageType: 'instant-article',
  referrer: 'www.dinside.no',
  site: 'www.dagbladet.no',
  url: 'http://dinside.no/a/93289234',
});

// Track a when the page loads
blink.pageLoad({
  clientHeight: 600,
  clientWidth: 800,
  pageId: 'front-page',
  plussData: { hasAccess: true, customerNumber: '123' },
  scrollHeight: 34500,
  url: 'http://dinside.no/a/93289234',
});

// Track page performance timings
blink.performance({
    domContentLoadedEventEnd: 100,
    domContentLoadedEventStart: 50,
    domInteractive: 200,
    loadEventEnd: 40,
    loadEventStart: 20,
    responseEnd: 30,
    responseStart: 10,
  },
})

// tracking web vitals (chromium specific api for now)
blink.trackChromeWebVitals({
  CLS: {
    value: 10,
    attribution: "domel>h1"
  },
  TTFB: {
    value: 111
  },
  LCP: {
    value: 10,
    attribution: "domel>h1"
  },
  INP: {
    value: 111
  },
  FCP: {
    value: 111
  },
  FID: {
    value: 111
  },
  visitDurationAtSend: 2021
})

// Track tcf consent
blink.consent({
  uuid:"4f842ac4-50a1-40c7-bc8f-23a4373122f3_25",
  tcfV2: "CP00b0AP00b0AAGABBENAYEgAAAAAEPAACgAAAANXgLgAIAAqAB4AEAAMgAaABzAD8AM0AfoBEQCLAEiAJSAXUA6QB5gD7QJkAmUBSYC8wGCANXADCgAQA5jwAQAcwDzFQAQAcwEygAA.YAAAAAAAAAAA",
  kind: "gdpr",
  consentGranted: true,
  consentedToAll: false,
  applies: false,
  },
})

// Track that the user clicked on an element / article
blink.click({
  pageId: 'front-page',
  url: 'http://seher.no/a/12931093',
  context: [
    'tag=a&i=1&n=1',
    'tag=article&id=article_69676674&class=columns,large-8,medium-8,preview,small-12&dataId=69678379&i=1&n=1'
  ],
});

/**
 * AD-RELATED FUNCTIONS
 */

// Track that an ad entered the screen by 30% og 50%, depending on the ad size
blink.adScreenEnter({ id: 'ad-topbanner' });

// Track that an ad left the screen, by having less than 30% or 50% inside view
blink.adScreenExit({id: 'ad-topbanner' });

// Track that an ad entered the screen by the first pixel
blink.adScreenEnter0({ id: 'ad-medium-rectangle' });

// Track that an ad is completely out of the screen
blink.adScreenExit0({id: 'ad-medium-rectangle' });

// Track that an ad started loading
blink.adLoad({
  id: 'ad-medium-rectangle',
  offsetTop: 200,
  offsetHeight: 450,
  scrollTop: 100
});

// Track data that is gotten from DFP, with internals only known by DFP gurus
blink.dfpImpressionViewable({
  id: 'ad-medium-rectangle',
  scrollTop: 100
});

blink.dfpSlotRenderEnded({
  id: 'ad-medium-rectangle',
  adUnitPath: '/8578/dagbladet.no/seksjoner/kjendis/artikkel',
  advertiserId: 29318043,
  campaignId: 123018391,
  creativeId: 123908149018,
  lineItemId: 344329408239,
  prebidWinningBid: "30.49",
  size: [300, 250]
  sourceAgnosticCreativeId: 123908149018,
  sourceAgnosticLineItemId: 344329408239,
  scrollTop: 100,
});

blink.dfpSlotOnload({
  id: 'ad-medium-rectangle1',
  name: 'medium-rectangle1',
  scrollTop: 100,
});

/**
 * ARTICLE-RELATED FUNCTIONS
 */

// Track that an article preview went into screen
blink.articlePreviewScreenEnter({
  context: ['tag=a&i=1&n=1', 'tag=article&i=1&n=1'],
  height: 380,
  personalizationParametersRequested: 'xavier-pluss',
  personalizationSystemUsed: 'cerebro',
  position: 5,
  title: 'Surprising title!',
  url: 'http://seher.no/kjendis/surprising-title/123980243',
  width: 400,
});

// Tracking of the users total activity time on a given article
blink.pageActivityStart({
  url: 'http://seher.no/kjendis/surprising-title/123980243', pageScrollOffsetY: 493
}); // sets the user as active for the next 10 seconds, unless a stop event is sent

blink.pageActivityStop({
  url: 'http://seher.no/kjendis/surprising-title/123980243'
}); // sets the user as inactive, and sends active time data

API

Page tracking

Should be called on a page initialization. Sets the pageView and computes values that will not change over the course of the page view.

pageInit({
  abCookie: number,
  commercialSegments: string,
  pageId: string,
  pageType: string,
  pageView: string,
  previousPageView: string,
  referrer: string,
  site: string,
  url: string,
});

Pageload

pageLoad({
  clientHeight: number,
  clientWidth: number,
  pageId: string,
  plussData: {
    hasAccess: boolean,
    customerNumber: string,
  },
  performance: {
    domContentLoadedEventEnd: number,
    domContentLoadedEventStart: number,
    domInteractive: number,
    domLoading: number,
    loadEventEnd: number,
    loadEventStart: number,
    responseEnd: number,
    responseStart: number,
  },
  scrollHeight: number,
  url: string,
});

Screen tracking

screenShow({
  time?: Date;
})

screenHide({
  time?: Date;
})

Clicks

interface ClickInput {
  id?: string;
  url?: string;
  context?: string[];
  pageId?: string;
}

click(input: ClickInput): void;

Ads

adScreenEnter({ id: string; pageId?: string; time?: Date });
adScreenExit({ id: string; pageId?: string; time?: Date });
adScreenEnter0({ id: string; pageId?: string; time?: Date });
adScreenExit0({ id: string; pageId?: string; time?: Date };
adLoad({
  id: string;
  offsetHeight: number;
  offsetTop: number;
  scrollTop: number;
};

// DFP Events
dfpImpressionViewable({
  id: string;
  scrollTop: number;
  time?: Date;
});

dfpSlotRenderEnded({
  adUnitPath: string;
  advertiserId: number;
  bidder: string;
  campaignId: number;
  creativeId: number;
  id: string;
  lineItemId: number;
  prebidWinningBid: string;
  scrollTop: number;
  size: number[];
  sourceAgnosticCreativeId: number;
  sourceAgnosticLineItemId: number;
});
dfpSlotOnload({
  id: string;
  name: string;
  scrollTop: number;
  time?: Date;
});

Impression

articlePreviewScreenEnter({
  context?: string[];
  height?: number;
  pageId?: string;
  personalizationSystemUsed?: string;
  personalizationParametersRequested?: string;
  position?: number;
  time?: Date;
  title: string;
  url: string;
  width?: number;
});

Active Time

pageActivityStart({
  url: string;
  pageId?: string;
  pageScrollOffsetY?: number;
  time?: Date;
}); // sets the user as active for the next 10 seconds, unless a stop event is sent
pageActivityStop({
  url: string;
  pageId?: string;
  time?: Date;
}); // sets the user as inactive, and sends active time data

Video

videoLoad({
  videoId: string;
  duration: number;
  position: number;
  title?: string;
  width: number;
  height: number;
  viewable: boolean;
  muted: boolean;
  quality?: string;
  withAdBlock: boolean;
  time?: Date;
  canBeSticky: boolean;
})

videoPlay({
  videoId: string;
  playerId: string;
  time?: Date;
  pageId?: string;
  muted: boolean;
  volume: number;
  position: number;
  reason: 'autostart' | 'interaction' | 'related-auto';
});

videoStop({
  videoId: string;
  playerId: string;
  time?: Date;
  pageId?: string;
  muted: boolean;
  volume: number;
  position: number;
  reason: 'pause' | 'complete' | 'exit';
  beforeunload: boolean; // Only added when beforeunload event is sent
});

videoAd({
  videoId: string;
  playerId: string;
  time?: Date;
  pageId?: string;
  adPosition: 'pre' | 'mid' | 'post';
  system?: string;
  title?: string;
  client?: string;
  viewable?: number;
  adId?: string;
  isBumper?: boolean;
  creativeId?: string;
  dealId?: string;
  duration?: number;
});

Player

playerShown({
  time: Date;
  muted: boolean;
  position: number;
  volume: number;
  sticky?: boolean;
  playerId: string;
  reason: 'viewable' | 'tabactive';
  pageId?: string;
});

playerHidden({
  time: Date;
  muted: boolean;
  position: number;
  volume: number;
  sticky?: boolean;
  playerId: string;
  reason: 'viewable' | 'tabclose' | 'tabhide';
  pageId?: string;
});

playerSticky({
  videoId: string;
  playerId: string;
  time?: Date;
  pageId?: string;
  sticky: boolean;
  closed?: boolean;
})

Sending

Explicitly tell blink to send all events. A common usecase is to send all events before a page is unloading.

sendAllEvents(time?: Date)

Box

Box tracking is for tracking elements on ap age that not neccesarily are article previews, but more general boxes.

boxScreenEnter({
  id: string;
  title?: string;
  height?: number;
  width?: number;
  pageId?: string;
  time?: Date;
})

TCF Consent

consent({
  uuid: string;
  tcfV2: string;
  kind: string;
  consentGranted: boolean;
  consentedToAll: boolean;
  applies: boolean;
})

Custom

custom({
  customDomain: string;
  customType: string;
  customContent?: string;
  customValue?: number;
  pageId?: string;
  time?: Date;
});

Readme

Keywords

Package Sidebar

Install

npm i @aller/blink

Weekly Downloads

568

Version

8.26.2

License

MIT

Unpacked Size

812 kB

Total Files

365

Last publish

Collaborators

  • aslak2800
  • roninjc
  • idanko
  • mariusjn
  • lobunto
  • konrad-j
  • oyvigri
  • goodleby
  • jimoe
  • vnorvik
  • kevinmidboe