Quick Start

Metrics like Navigation Timing, Network Information, FCP, FID, LCP, CLS and TBT are default reported with Perfume; All results will be reported to the analyticsTracker callback, and the code below is just one way for you to organize your tracking, feel free to tweak it suit your needs.

Oh btw, you're being served a lighter experiencefull experience based on your hardware, network conditions and data saver preference.

// Device Information
Network information: {{ networkInformation?.effectiveType || '--' }}
Device Memory: {{ navigatorInformation?.deviceMemory || '--' }}
Hardware Concurrency: {{ navigatorInformation?.hardwareConcurrency || '--' }}
Data Saver preference: {{ networkInformation?.saveData }}

// Main Performance Metrics
Time To First Byte: {{ ttfb || 0 }}ms
First Contentful Paint: {{ fcp }} ms
First Input Delay: {{ fid }} ms
Largest Contentful Paint: {{ lcp }} ms
Cumulative Layout Shift: {{ cls }} score
Total Blocking Time: {{ tbt }} ms

// Secondary Performance Metrics
// These metrics activate on a set delay or when the tab changes visibility
// Experimental Performance metrics
dataConsumption: {{ dataConsumption }}
Hero logo element timing: {{ elHeroLogo }} ms
Page title element timing: {{ elPageTitle }} ms

const perfume = new Perfume({{'{'}}
  analyticsTracker: (options) => {{'{'}}
    const {{'{'}} metricName, data, navigatorInformation {{'}'}} = options;
    switch (metricName) {{'{'}}
      case 'navigationTiming':
        if (data && data.timeToFirstByte) {{'{'}}
          myAnalyticsTool.track('navigationTiming', data);
        {{'}'}}
        break;
      case 'networkInformation':
        if (data && data.effectiveType) {{'{'}}
          myAnalyticsTool.track('networkInformation', data);
        {{'}'}}
        break;
      case 'TTFB':
        myAnalyticsTool.track('timeToFirstByte', {{'{'}} duration: data {{'}'}});
        break;
      case 'FCP':
        myAnalyticsTool.track('firstContentfulPaint', {{'{'}} duration: data {{'}'}});
        break;
      case 'FID':
        myAnalyticsTool.track('firstInputDelay', {{'{'}} duration: data {{'}'}});
        break;
      case 'LCP':
        myAnalyticsTool.track('largestContentfulPaint', {{'{'}} duration: data {{'}'}});
        break;
      case 'CLS':
        myAnalyticsTool.track('cumulativeLayoutShift', {{'{'}} duration: data {{'}'}});
        break;
      case 'TBT':
        myAnalyticsTool.track('totalBlockingTime', {{'{'}} duration: data {{'}'}});
        break;
      default:
        myAnalyticsTool.track(metricName, {{'{'}} duration: data {{'}'}});
        break;
    {{'}'}}
  {{'}'}},
{{'}'}});

In a world with widely varying device capabilities, a one-size-fits-all event doesn’t always work. Perfume adds data enrichment to all events so we can better understand the real world experiences:

Based on the Navigator APIs the library can help us differentiate between a low-end and a high-end device/experience:

Performance audits

Coo coo coo cool, let's learn something new about measuring page's speed performance.

Navigation Timing

Navigation Timing collects performance metrics for the life and timings of a network request.

Perfume helps expose some of the key metrics you might need.

Navigation Timing: {{ navigationTiming }}

First Contentful Paint (FCP)

First Contentful Paint is the exact time taken for the browser to render the first bit of content from the DOM, which can be anything from an important image, text, or even the small SVG at the bottom of the page.

First Contentful Paint: {{ fcp }} ms

Largest Contentful Paint (LCP)

Largest Contentful Paint is an important, user-centric metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful.

We end the Largest Contentful Paint measure at two points: when First Input Delay happen and when the page's lifecycle state changes to hidden.

Largest Contentful Paint: {{ lcp }} ms

First Input Delay (FID)

First Input Delay measures the time from when a user first interacts with your site (i.e. when they click a link, tap on a button) to the time when the browser is actually able to respond to that interaction.

First Input Delay: {{ fid }} ms

Cumulative Layout Shift (CLS)

Cumulative Layout Shift is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful.

Cumulative Layout Shift: {{ cls }}

Total Blocking Time (TBT)

Total Blocking Time is an important, user-centric metric for measuring load responsiveness because it helps quantify the severity of how non-interactive a page is prior to it becoming reliably interactive—a low TBT helps ensure that the page is usable.

We end the Total Blocking Time measure 10 seconds after FID.

Total Blocking Time: {{ tbt }} ms

Navigationg Total Blocking Time (NTBT)

This metric measures the amount of time the application may be blocked from processing code during the 2s window after a user navigates from page A to page B. The NTBT metric is the summation of the blocking time of all long tasks in the 2s window after this method is invoked.

Because this library is navigation agnostic, we have this method to mark when the navigation starts.

If this method is called before the 2s window ends; it will trigger a new NTBT measurement and interrupt the previous one.

{{ ntbt }}ms

Resource Timing

Resource Timing collects performance metrics for document-dependent resources. Stuff like style sheets, scripts, images, et cetera.

Perfume helps expose all PerformanceResourceTiming entries and groups data data consumption by Kb used.

Data Consumption: {{ dataConsumption }}

const perfume = new Perfume({{'{'}}
  resourceTiming: true,
  analyticsTracker: ({{'{'}} metricName, data {{'}'}}) => {{'{'}}
    myAnalyticsTool.track(metricName, data);
  {{'}'}})
{{'}'}});

Annotate metrics in the DevTools

Performance.mark ( User Timing API) is used to create an application-defined peformance entry in the browser's performance entry buffer.

{{ logFibonacci }}

const perfume = new Perfume({{'{'}}
  analyticsTracker: ({{'{'}} metricName, data {{'}'}}) => {{'{'}}
    myAnalyticsTool.track(metricName, data);
  {{'}'}})
{{'}'}});
perfume.start('fibonacci');
fibonacci(400);
perfume.end('fibonacci');
Annotate metrics in the DevTools

Component First Paint

Use perfume.endPaint() to mark the point, immediately after the browser renders pixels to the screen.

const perfume = new Perfume({{'{'}}
    analyticsTracker: ({{'{'}} metricName, duration {{'}'}}) => {{'{'}}
      myAnalyticsTool.track(metricName, duration);
    {{'}'}})
  {{'}'}});
  perfume.start('openDialog');
  this.dialog.open();
  perfume.endPaint('openDialog');
Annotate Component First Paint (CFP)

Element Timing

Add the elementtiming attribute to track when image elements and text nodes with are displayed on screen using the Element Timing API

Hero logo element timing: {{ elHeroLogo }} ms
Page title element timing: {{ elPageTitle }} ms

{{'<'}}h1 elementtiming="page-title" class="title"{{'>'}}Perfume.js{{'<'}}/h1{{'>'}}