> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nekt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Google PageSpeed Insights as a data source

> Bring data from Google PageSpeed Insights to your Lakehouse.

Google PageSpeed Insights runs a live [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview) analysis of a web page and reports how well it performs. For each page it returns the performance, accessibility, best practices and SEO scores, the lab measurements behind those scores, and the Core Web Vitals that real Chrome users actually experienced on that page, taken from the [Chrome UX Report](https://developer.chrome.com/docs/crux).

Unlike most sources, PageSpeed Insights has nothing to list and no history to backfill: it analyzes the pages you point it at, as they are right now. You choose which URLs to monitor, and every run of this source records a fresh measurement of each one. Over time those measurements build into a performance history you can trend, alert on, and join with the rest of your data.

## Configuring Google PageSpeed Insights as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the Google PageSpeed Insights option from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

This source needs no credentials. PageSpeed Insights measures publicly reachable pages and Nekt provides the API access, so you only have to say which pages to watch.

The following configurations are available:

* **URLs**: The full URLs of the pages you want to monitor, including the scheme (for example `https://www.example.com/pricing`). Add one entry per page. PageSpeed Insights analyzes a single page at a time, so it measures exactly the URLs you list here and nothing else. To follow a whole site, list the pages that matter most: the homepage, the main landing pages, and your highest-traffic templates.

* **Form Factors**: (Default: `MOBILE` and `DESKTOP`) The device profiles to analyze each URL for. Scores differ substantially between the two, because Lighthouse applies stricter thresholds and simulates a slower CPU and network on mobile. Comparing mobile against desktop is rarely meaningful; comparing the same form factor over time is.

* **Lighthouse Categories**: (Default: `PERFORMANCE`, `ACCESSIBILITY`, `BEST_PRACTICES`, `SEO`) Which categories to run. Also accepts `AGENTIC_BROWSING` and `PWA` (deprecated by Lighthouse 12.0). Requesting fewer categories makes each analysis faster, but the scores and audits for the categories you leave out will be empty.

* **Locale**: The language used for audit titles, descriptions and recommendations, for example `en`, `pt-BR` or `es`. This only affects wording, never the scores or measurements.

Once you're done, click **Next**.

<Note>Each analysis takes roughly 10 to 30 seconds, and one is run per URL per form factor. Twenty URLs on both form factors is around 40 analyses, so expect a run of several minutes. All three streams share the same analyses, so selecting all of them costs no extra time.</Note>

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams that are relevant to your analysis. You can select entire groups of streams or pick specific ones.

> Tip: The stream can be found more easily by typing its name.

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.

* **Layer**: choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
* **Folder**: a folder can be created inside the selected layer to group all tables being created from this new data source.
* **Table name**: we suggest a name, but feel free to customize it. You have the option to add a **prefix** to all tables at once and make this process faster!
* **Sync Type**: you can choose between INCREMENTAL and FULL\_TABLE.
  * Incremental: every time the extraction happens, we'll get only the new data - which is good if, for example, you want to keep every record ever fetched.
  * Full table: every time the extraction happens, we'll get the current state of the data - which is good if, for example, you don't want to have deleted data in your catalog.

<Warning>Use **INCREMENTAL** for this source. Each run measures the pages as they are at that moment, so incremental keeps every measurement and lets you trend performance over time. FULL\_TABLE would replace the previous run's rows and leave you with only the latest snapshot.</Warning>

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/get-started/core-concepts/triggers), consider how often you want data to be extracted from this source. This decision usually depends on how frequently you need the new table data updated (every day, once a week, or only at specific times).

<Note>A daily trigger suits most sites. The Chrome UX Report field data is a 28-day rolling aggregate, so it moves slowly and there is little value in analyzing more often than once a day. The lab measurements do vary between runs even on an unchanged page, so read trends rather than single data points.</Note>

Optionally, you can define some additional settings:

* Configure Delta Log Retention and determine for how long we should store old states of this table as it gets updated. Read more about this resource [here](https://docs.nekt.com/get-started/core-concepts/resource-control).
* Determine when to execute an **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**. This will complement the incremental data extractions, ensuring that your data is completely synchronized with your source every once in a while.

Once you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the source extraction by clicking on the arrow button. Once executed, your data will appear in your Catalog.

<Warning>For you to be able to see it on your [Catalog](https://app.nekt.ai/catalog), you need at least one successful source run.</Warning>

## Understanding the data

A few things are worth knowing before you query these tables.

**Lab data versus field data.** Lighthouse measures the page in a controlled environment: those are the *lab* metrics (`largest_contentful_paint_ms`, `total_blocking_time_ms`, and so on). The Chrome UX Report reports what real Chrome users experienced over the previous 28 days: those are the *field* metrics (the `field_` and `origin_field_` columns, and the whole `crux_metrics` stream). Lab data is reproducible and available for any page; field data is the ground truth but only exists for pages with enough real traffic. They will not agree, and that is expected.

**Scores are 0 to 1.** Multiply by 100 to get the familiar 0-100 Lighthouse score. A score is `null` when that category was not run.

**Cumulative Layout Shift is scaled in field data.** The Chrome UX Report returns CLS multiplied by 100, so `field_cls = 10` means a CLS of 0.10. The lab `cumulative_layout_shift` column is not scaled.

**Pages with little traffic fall back to the origin.** When a specific page has too few real-user samples, `field_origin_fallback` is `true` and the field metrics describe the whole origin rather than that page.

**A page that fails to load is skipped, not fatal.** If PageSpeed Insights cannot analyze a URL (the page is unreachable, times out, or sits behind a login), that URL is reported in the run log and skipped for that run. The other URLs are unaffected.

# Streams and Fields

All three streams join on `url`, `strategy` and `analysis_utc_timestamp`.

Below you'll find all available data streams from Google PageSpeed Insights and their corresponding fields:

<AccordionGroup>
  <Accordion title="Pagespeed Results">
    One row per URL per form factor, per run. The headline table: category scores, the lab metrics behind them, and the Core Web Vitals for both the page and its origin.

    **Key Fields:**

    * `url` - URL that was submitted for analysis, as configured in the connector
    * `strategy` - Form factor the page was analyzed for: MOBILE or DESKTOP
    * `analysis_utc_timestamp` - UTC timestamp of when this analysis ran, used as the incremental replication key
    * `id` - Canonicalized and final URL of the analyzed document, after following any redirects
    * `kind` - Kind of result returned by the API
    * `captcha_result` - Result of the CAPTCHA verification, if one was required

    **Category Scores:**

    * `performance_score` - Lighthouse performance score between 0 and 1
    * `accessibility_score` - Lighthouse accessibility score between 0 and 1
    * `best_practices_score` - Lighthouse best practices score between 0 and 1
    * `seo_score` - Lighthouse SEO score between 0 and 1
    * `pwa_score` - Progressive Web App score, deprecated by Lighthouse 12.0
    * `agentic_browsing_score` - How well the page can be rendered by an automated browsing agent

    **Lab Metrics (measured by Lighthouse):**

    * `first_contentful_paint_ms` - When the first text or image was painted
    * `largest_contentful_paint_ms` - When the largest content element became visible. A Core Web Vital
    * `speed_index_ms` - How quickly the page contents are visibly populated
    * `total_blocking_time_ms` - Total time the main thread was blocked long enough to prevent input responsiveness
    * `cumulative_layout_shift` - Unitless score of how much visible content shifted unexpectedly. A Core Web Vital
    * `time_to_interactive_ms` - When the page became reliably able to respond to user input
    * `server_response_time_ms` - Server response time for the main document request
    * `max_potential_fid_ms` - Maximum potential First Input Delay, based on the longest main-thread task
    * `first_meaningful_paint_ms` - When the page's primary content became visible

    **Field Data — this page (real Chrome users, 28-day window):**

    * `field_data_available` - Whether the Chrome UX Report had enough traffic to report data for this page
    * `field_id` - URL or URL pattern the page-level metrics were aggregated over
    * `field_overall_category` - Overall real-user speed rating of this page: FAST, AVERAGE or SLOW
    * `field_origin_fallback` - True when the page had too little traffic and the data falls back to the whole origin
    * `field_lcp_ms` - 75th percentile Largest Contentful Paint. A Core Web Vital
    * `field_inp_ms` - 75th percentile Interaction to Next Paint. A Core Web Vital
    * `field_cls` - 75th percentile Cumulative Layout Shift, returned multiplied by 100. A Core Web Vital
    * `field_fcp_ms` - 75th percentile First Contentful Paint
    * `field_ttfb_ms` - 75th percentile Time to First Byte
    * `field_fid_ms` - 75th percentile First Input Delay, superseded by Interaction to Next Paint

    **Field Data — whole origin:**

    * `origin_field_data_available` - Whether field data was reported across the whole origin
    * `origin_field_id` - Origin the metrics were aggregated over
    * `origin_field_overall_category` - Overall real-user speed rating of the origin: FAST, AVERAGE or SLOW
    * `origin_field_lcp_ms` - 75th percentile Largest Contentful Paint across the origin
    * `origin_field_inp_ms` - 75th percentile Interaction to Next Paint across the origin
    * `origin_field_cls` - 75th percentile Cumulative Layout Shift across the origin, multiplied by 100
    * `origin_field_fcp_ms` - 75th percentile First Contentful Paint across the origin
    * `origin_field_ttfb_ms` - 75th percentile Time to First Byte across the origin
    * `origin_field_fid_ms` - 75th percentile First Input Delay across the origin

    **Run Metadata:**

    * `lighthouse_version` - Version of Lighthouse that generated this result
    * `requested_url` - URL Lighthouse was originally asked to audit
    * `final_url` - Final resolved URL that was actually audited, after redirects
    * `main_document_url` - URL of the main document request of the final navigation
    * `final_displayed_url` - URL displayed in the browser once Lighthouse finished
    * `fetch_time` - Time at which Lighthouse fetched the page
    * `user_agent` - User agent string used to run the analysis
    * `environment_host_user_agent` - User agent of the Chrome version that ran the analysis
    * `environment_network_user_agent` - User agent sent over the network during the analysis
    * `environment_benchmark_index` - Benchmark index of the analysis machine, indicating its rough device class
    * `config_locale` - Locale the results were formatted in
    * `config_form_factor` - Form factor Lighthouse scored the run as
    * `config_channel` - Channel Lighthouse was run from
    * `timing_total_ms` - Total time Lighthouse took to run the analysis
    * `runtime_error_code` - Lighthouse error code when the run hit a problem serious enough to make the result unreliable
    * `runtime_error_message` - Human readable explanation of the runtime error
    * `run_warnings` - Warnings Lighthouse raised during the run, which may explain unusual scores (JSON array)
    * `stack_packs` - Platform-specific advice, for example WordPress or React, matched to this page (JSON array)
    * `pagespeed_version_major` - Major version of PageSpeed that generated this result
    * `pagespeed_version_minor` - Minor version of PageSpeed that generated this result
  </Accordion>

  <Accordion title="Lighthouse Audits">
    One row per individual Lighthouse audit, roughly 150 per analysis. These are the specific checks behind each category score, such as "Eliminate render-blocking resources" or "Background and foreground colors have a sufficient contrast ratio". This is where the actionable detail lives: what is wrong, how much it costs, and which resources are responsible.

    **Key Fields:**

    * `url` - URL that was submitted for analysis, as configured in the connector
    * `strategy` - Form factor the page was analyzed for: MOBILE or DESKTOP
    * `analysis_utc_timestamp` - UTC timestamp of the analysis this audit belongs to, used as the incremental replication key
    * `audit_id` - Lighthouse identifier of the audit, for example `render-blocking-resources`

    **Result:**

    * `title` - Human readable name of the audit as shown in the Lighthouse report
    * `description` - Explanation of what the audit checks and why it matters
    * `score` - Score of the audit between 0 and 1. Null for informative or manual audits
    * `score_display_mode` - How to interpret the score: binary, numeric, informative, notApplicable, manual or error
    * `numeric_value` - Measured value behind the audit, with a meaning specific to it
    * `numeric_unit` - Unit of the numeric value, for example millisecond, byte or element
    * `display_value` - Preformatted summary as shown in the report, for example "Potential savings of 120 KiB"
    * `explanation` - Explanation of the failures found by the audit, when it failed
    * `error_message` - Error thrown inside the audit, when it could not be evaluated

    **Classification:**

    * `categories` - Lighthouse categories that reference this audit, for example `['performance', 'seo']`
    * `acronym` - Conventional acronym when the audit is a headline metric, for example LCP or CLS
    * `group` - Category group the audit is displayed under, for example metrics or diagnostics
    * `weight` - Weight this audit's score carries in its category score. Zero means it is reported but does not affect the score

    **Estimated Savings:**

    * `metric_savings_lcp_ms` - Estimated Largest Contentful Paint improvement if this audit were fixed
    * `metric_savings_fcp_ms` - Estimated First Contentful Paint improvement if this audit were fixed
    * `metric_savings_tbt_ms` - Estimated Total Blocking Time improvement if this audit were fixed
    * `metric_savings_cls` - Estimated Cumulative Layout Shift improvement if this audit were fixed
    * `metric_savings_inp_ms` - Estimated Interaction to Next Paint improvement if this audit were fixed

    **Details:**

    * `warnings` - Warnings raised while running the audit (JSON array)
    * `details` - Freeform details, whose shape differs per audit type. Typically the table of offending resources or elements with the potential savings for each (JSON object)
  </Accordion>

  <Accordion title="CrUX Metrics">
    One row per Core Web Vitals field metric per scope, from the Chrome UX Report. Where `pagespeed_results` carries the headline percentiles, this stream keeps the full distribution: for each metric, the share of real Chrome users who experienced it as good, needing improvement, or poor. That breakdown is what shows whether a bad 75th percentile is a broad problem or a long tail affecting a minority of visitors.

    Reported twice, once for the specific page and once for the whole origin, distinguished by `scope`. Only available for pages and origins with enough real-user traffic.

    **Key Fields:**

    * `url` - URL that was submitted for analysis, as configured in the connector
    * `strategy` - Form factor the page was analyzed for: MOBILE or DESKTOP
    * `analysis_utc_timestamp` - UTC timestamp of the analysis this metric belongs to, used as the incremental replication key
    * `scope` - Whether the metric is aggregated for this specific page (`page`) or across the whole origin (`origin`)
    * `metric_id` - Chrome UX Report metric identifier, for example `LARGEST_CONTENTFUL_PAINT_MS`, `INTERACTION_TO_NEXT_PAINT`, `CUMULATIVE_LAYOUT_SHIFT_SCORE` or `EXPERIMENTAL_TIME_TO_FIRST_BYTE`

    **Measurements:**

    * `percentile` - 75th percentile value across real Chrome users. In milliseconds for timing metrics; for `CUMULATIVE_LAYOUT_SHIFT_SCORE` it is the score multiplied by 100
    * `median` - Median value of the metric across real Chrome users
    * `category` - Rating of this individual metric: FAST, AVERAGE or SLOW
    * `form_factor` - Device class the metric was collected on, when reported

    **Distribution:**

    * `distribution_good_proportion` - Share of real-user page loads in the "good" bucket, between 0 and 1
    * `distribution_needs_improvement_proportion` - Share of page loads in the "needs improvement" bucket
    * `distribution_poor_proportion` - Share of page loads in the "poor" bucket
    * `distributions` - Full bucket breakdown with each bucket's min and max bounds and its proportion (JSON array)

    **Context:**

    * `experience_id` - URL, URL pattern or origin the metric was aggregated over
    * `initial_url` - URL originally requested, which can differ from the resolved experience id
    * `origin_fallback` - True when the page had too little traffic and these figures fall back to the whole origin
    * `overall_category` - Overall real-user speed rating of the page or origin: FAST, AVERAGE or SLOW
  </Accordion>
</AccordionGroup>
