---
title: Custom UI - Connection Information for your Solution
description: In its simplest form, you can use it as a traffic-light display for good / ok / bad connection. We also provide some more details and values, ...
---

[Eyeson Blog ](https://blog.eyeson.com)

# [Custom UI - Connection Information for your Solution](https://blog.eyeson.com/custom-ui-connection-information-for-your-solution)

 Written by [Stefan Benicke](https://blog.eyeson.com/author/stefan-benicke) | December 22, 2021

You can include a connection quality indicator in your custom UI. This will give your users quick feedback about their current audio/video quality.

In its simplest form, you can use it as a traffic-light display for good / ok / bad connection. We also provide some more details and values, like bitrate, jitter, packet loss, and round-trip time.

You can read more about the data in the [help center article](https://help.eyeson.com/connection-info).

### Initialize Statistics

You have to listen for the `statistics_ready` event and this event includes the statistics interface with its important method `onUpdate`.

`onUpdate` is triggered roughly every 1s and provides an object with all values.

```
eyeson.onEvent(event => {
    if (event.type === 'statistics_ready') {
        event.statistics.onUpdate(showStatistics);
    }
});

function showStatistics(stats) {
    /*...*/
}

eyeson.start(/*...*/);
```

### Statistics data

The `onUpdate` function is called with a statistics object containing the following data:

- `status` can be “good”, “ok”, “bad”, or even “no connection” (please use `Status.GOOD` etc.)
- `bitrateSend` and `bitrateRecv` are audio+video bitrates either send or received. Values are in kbps.
- `jitter` is the sender’s jitter and it takes the worse value, either audio or video. Values are in s.
- `packetLoss` is the sender’s packet loss and it takes the worse value, either audio or video. Values are between 0 and 1.0.
- `roundTripTime` is the sender’s round-trip time and it takes the worse value, either audio or video. Values are in s.
- `nack` is the sender’s video negative-acknowledge count rate. Values are between 0 and 1.0.

**Heads-up:** In some cases values are `null`. There are browsers where not all parameters are available.

**Good to know:** All values are the average over the last 3 entries (roughly the last 3 seconds) to avoid high-value jumps.

### Quality status

As the simplest approach, you might want to show only the connection quality status as a traffic-light indicator.

The `ConnectionStatistics` interface provides a `Status` object with named keys for the `stats.status` value.

Currently, it contains 4 named keys: `GOOD`, `OK`, `BAD`, and `NO_CONNECTION`.

```
import { ConnectionStatistics } from 'eyeson';

const { Status } = ConnectionStatistics;

const connectionInfo = {};
connectionInfo[Status.GOOD] = { title: 'Excellent', className: 'good' };
connectionInfo[Status.OK] = { title: 'Unstable', className: 'ok' };
connectionInfo[Status.BAD] = { title: 'Poor', className: 'bad' };
connectionInfo[Status.NO_CONNECTION] = { title: 'No connection', className: 'none' };

function showStatistics(stats) {
    indicator.className = connectionInfo[stats.status].className;
    indicator.textContent = connectionInfo[stats.status].title;
}
```

### Full example

The following example will show all available data and update automatically.

```
import { ConnectionStatistics } from 'eyeson';

const { Status } = ConnectionStatistics;
const numberFormat = new Intl.NumberFormat('en', { maximumFractionDigits: 0 });
const percentFormat = new Intl.NumberFormat('en', { style: 'percent', maximumFractionDigits: 0 });

const connectionInfo = {};
connectionInfo[Status.GOOD] = { title: 'Excellent', className: 'good' };
connectionInfo[Status.OK] = { title: 'Unstable', className: 'ok' };
connectionInfo[Status.BAD] = { title: 'Poor', className: 'bad' };
connectionInfo[Status.NO_CONNECTION] = { title: 'No connection', className: 'none' };

const showStatistics = stats => {
    statisticsIcon.className = connectionInfo[stats.status].className;
    outputStatus.textContent = connectionInfo[stats.status].title;
    outputBitrateSend.textContent = numberFormat.format(stats.bitrateSend) + ' kbps';
    outputBitrateReceive.textContent = numberFormat.format(stats.bitrateRecv) + ' kbps';
    if (stats.jitter !== null) {
        outputJitter.textContent = numberFormat.format(stats.jitter * 1000) + ' ms';
    }
    if (stats.packetLoss !== null) {
        outputPacketLoss.textContent = percentFormat.format(stats.packetLoss);
    }
    if (stats.roundTripTime !== null) {
        outputRoundTripTime.textContent = numberFormat.format(stats.roundTripTime * 1000) + ' ms';
    }
    if (stats.nack !== null) {
        outputNack.textContent = percentFormat.format(stats.nack);
    }
};

eyeson.onEvent(event => {
    if (event.type === 'statistics_ready') {
        event.statistics.onUpdate(showStatistics);
    }
});

eyeson.start(/*...*/);
```

### More info

Whenever `eyeson.destroy()` is called and the session ends, the instance of the statistics will automatically shut down. So the `onUpdate` event is not triggered anymore.

[View full post](https://blog.eyeson.com/custom-ui-connection-information-for-your-solution)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Stefan Benicke"
  },
  "dateModified" : "2023-06-29T08:29:22.151Z",
  "datePublished" : "2021-12-22T13:39:00Z",
  "headline" : "Custom UI - Connection Information for your Solution",
  "image" : {
    "@type" : "ImageObject",
    "height" : 500,
    "url" : "https://f.hubspotusercontent40.net/hubfs/7502097/connection-info.jpg",
    "width" : 714
  },
  "mainEntityOfPage" : "https://blog.eyeson.com/custom-ui-connection-information-for-your-solution",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60.0,
      "url" : "https://www.eyeson.com/hubfs/eyeson_logo_amp-60.png",
      "width" : 238.0
    },
    "name" : "Eyeson Blog | Eyeson One View"
  }
}
```