We've created a set of resources to help you ensure your site remains available and accessible to all during the COVID-19 situation.

Getting started with the Chrome UX Report API

The Chrome User Experience Report provides metrics for how real-world Chrome users experience popular destinations on the web. You can integrate with the Chrome UX Report API to monitor metrics, extract insights, and better understand the user's experience.

Prerequisites

This tutorial assumes that you have general knowledge of command line interfaces and web development. You will also need an API key to use the API.

Acquiring and using an API key

Get a Key

Or create one in the Credentials page.

After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs.

The API key is safe for embedding in URLs; it doesn't need any encoding.

cURL

To try out the Chrome UX Report API from the command line:

  1. Open a terminal.
  2. In the following command, replace API_KEY in the request URL with a key you’ve generated:

    curl https://chromeuxreport.googleapis.com/v1/records:queryRecord?key=API_KEY \
      --header 'Content-Type: application/json'   --data '{"origin":"https://google.com/"}'
    
  3. The response is a JSON object. See Response to learn more about each of the properties in the response object.

    {
      "record": {
        "key": {
          "formFactor": "PHONE",
          "origin": "https://google.com"
        },
        "metrics": {
          "largest_contentful_paint": {
            "histogram": [
              {
                "start": 0,
                "end": 2500,
                "density": 0.73454920019389236
              },
              {
                "start": 2500,
                "end": 4000,
                "density": 0.17080707707222487
              },
              {
                "start": 4000,
                "density": 0.094643722733883481
              }
            ],
            "percentiles": {
              "p75": 2579
            }
          },
          // ...
        }
      },
      "urlNormalizationDetails": {
        "originalUrl": "https://google.com/",
        "normalizedUrl": "https://google.com"
      }
    }
    

JavaScript

To try out the CrUX API on the web:

  1. Insert Your API key.

    var apiKey = "API_KEY";
    
  2. Open the code in JS Fiddle and run! The code uses the CrUX API to get the performance data for https://example.com, and then displays the results.

    JavaScript

    /**
     * @url https://developers.google.com/web/tools/chrome-user-experience-report/api/guides/getting-started
     */
    const CrUXApiUtil = {
      /**
       * Query the CrUX API for metric records
       * @param {{origin?: string, url?: string, formFactor?: string,  metrics?: Array<string>}} requestBody
       * @param {string} apiKey
       * @return {{record: {key: Object, metrics: Map<string, {histogram: Array<{ start: number, end?: number, density: number}>}>}, urlNormalizationDetails: Object}}   */
      query: async function (requestBody, apiKey) {
        const endpointUrl = 'https://chromeuxreport.googleapis.com/v1/records:queryRecord';
        const resp = await fetch(`${endpointUrl}?key=${apiKey}`, {
          method: 'POST',
          body: JSON.stringify(requestBody),
        });
        const json = await resp.json();
        if (!resp.ok) throw new Error(json.error.message);
        return json;
      }
    };
    
    // Gather the data for example.com and display it
    (async function () {
      const json = await CrUXApiUtil.query({origin: 'https://example.com/'}, apiKey);
      console.log('CrUX API response:', json);
    
      const labeledMetrics = labelMetricData(json.record.metrics);
    
      // Display metric results
      for (const metric of labeledMetrics) {
        const metricEl = document.createElement('section');
    
        const titleEl = document.createElement('h2');
        titleEl.textContent = metric.acronym;
    
        const [descEl, barsEl] = createDescriptionAndBars(metric.labeledBins);
    
        metricEl.append(titleEl, descEl, barsEl);
        document.getElementById('wrapper').append(metricEl);
      }
    })();
    
    /**
     * Utility method to transform the response's metric data into an array of usable metric objects
     * Example return value:
      [
        {
          "acronym": "FCP",
          "name": "first_contentful_paint",
          "labeledBins": [{
            "label": "good",
            "percentage": 43.51,
            "start": 0,
            "end": 1000,
            "density": 0.4351
          }, // ... (other bins) ]
        }, // ... (other metrics) ]
    *
    * @return {{acronym: string, name: string, labelsBins: Array<{label: 'good'|'needs improvement'|'poor', percentage: number, start: number, end?: number, density: number}>}}*/
    function labelMetricData(metrics) {
      const nameToAcronymMap = {
        first_contentful_paint: 'FCP',
        largest_contentful_paint: 'LCP',
        first_input_delay: 'FID',
        cumulative_layout_shift: 'CLS',
      };
    
      return Object.entries(metrics).map(([metricName, metricData]) => {
        const standardBinLabels = ['good', 'needs improvement', 'poor'];
        const metricBins = metricData.histogram;
    
        // We assume there are 3 histogram bins and they're in order of: good => poor
        const labeledBins = metricBins.map((bin, i) => {
          // Assign a good/poor label, calculate a percentage, and add retain all existing bin properties
          return {
            label: standardBinLabels[i],
            percentage: bin.density * 100,
            ...bin,
          };
        });
    
        return {
          acronym: nameToAcronymMap[metricName],
          name: metricName,
          labeledBins,
        };
      });
    }
    
    // Create the three bars w/ a 3-column grid
    // This consumes the output from labelMetricData, not a raw API response.
    function createDescriptionAndBars(labeledBins) {
      const descEl = document.createElement('p');
      // Example: 'good: 43.63%, needs improvement: 42.10%, poor: 14.27%'
      descEl.textContent = labeledBins
        .map(bin => `${bin.label}: ${bin.percentage.toFixed(2)}%`)
        .join(', ');
    
      let barsEl = document.createElement('div');
    
      for (const bin of labeledBins) {
        const barEl = document.createElement('div');
        // Reuse the label for the styling class, changing any spaces:  `needs improvement` => `needs-improvement`
        barEl.classList.add(`box-${bin.label.replace(' ', '-')}`);
        // Add tooltip to share the size of each bin
        barEl.title = `bin start: ${bin.start}, bin end: ${bin.end}`;
        barsEl.append(barEl);
      }
    
      // Set the width of the bar columns based on metric bins
      // Ex: `grid-template-columns: 43.51% 42.26% 14.23%`;
      barsEl.style.gridTemplateColumns = labeledBins.map(bin => `${bin.percentage}%`).join(' ');
      barsEl.classList.add(`grid-container`);
    
      return [descEl, barsEl];
    }
    
    

    HTML

    <div id="wrapper">
      <h1>Chrome User Experience Report API demo</h1>
      <p>The field data collected over the last 28 days.</p>
    </div>
    
    

    CSS

    #wrapper {
      margin: auto;
      width: 70%;
      font-family: sans-serif;
    }
    
    .grid-container {
      display: grid;
      grid-template-rows: 50px;
      grid-template-areas: '. . .';
      padding-bottom: 10px;
    }
    
    .box-good {
      background-color: hsl(118, 41%, 49%);
    }
    .box-needs-improvement {
      background-color: hsl(31, 78%, 53%);
    }
    .box-poor {
      background-color: hsl(359, 80%, 50%);
    }
    
    
  3. Upon successful run, your page will look like Figure 1. Chrome UX Report API JavaScript Demo Figure 1. The JavaScript demo

Next Steps