Core Web Vitals Monitor for Magento 2
Measures LCP, INP and CLS from real visitors on every Magento 2 storefront page with the browser PerformanceObserver API. It also adds dns-prefetch and preconnect hints, and the tracking script is about 3 KB gzipped.
- Free
- Themes listed: Hyvä + Luma
composer require mage2kishan/module-corewebvitals
- Package requirementsRead the source documentation
- Developer profileView Upwork profile
- Themes listedHyvä + Luma
- PHP versions listed8.2, 8.3, 8.4
- Installation questionsDiscuss your store setup
What it does for your store
The main features, as listed in the module documentation.
-
LCP tracking
Largest Contentful Paint, captured on the final paint event before user input
-
FID tracking
First Input Delay for legacy browsers and backwards compatibility
-
INP tracking
Interaction to Next Paint, the official replacement CWV since March 2024
-
CLS tracking
Cumulative Layout Shift with session-window aggregation
Installation
Example commands from the Magento root. Follow the package instructions and your staging and deployment process.
- 1Check the releaseMatch Magento, PHP, theme and dependency requirements.
- 2Install on stagingReview Composer changes and follow the package instructions.
- 3Configure and verifyUse the documented settings and test the affected features.
$ composer require mage2kishan/module-corewebvitals $ bin/magento setup:upgrade $ bin/magento setup:di:compile $ bin/magento setup:static-content:deploy -f $ bin/magento cache:clean
Listed requirements
These are the details supplied in this listing. Confirm the selected release supports your Magento edition, PHP and storefront.
| Magento versions listed | 2.4.7, 2.4.8 |
|---|---|
| PHP versions listed | 8.2, 8.3, 8.4 |
| Themes listed | Hyvä, Luma |
| Composer package | mage2kishan/module-corewebvitals |
Documentation
Product details and setup guidance. Check the package repository for release-specific instructions.
Overview
Panth Core Web Vitals Monitor is a performance tracking and optimization module for Magento 2 and Adobe Commerce that captures real-user LCP, INP, CLS, FID, TTFB, and FCP through the browser PerformanceObserver API. Metrics post to Google Analytics 4 or a custom beacon endpoint, so admins see field data, not synthetic Lighthouse runs.
The Core Web Vitals tracker ships as a ~3 KB gzipped vanilla JS file loaded async and deferred, with zero runtime dependencies. INP, the official replacement metric since March 2024, is captured alongside legacy FID for backward compatibility. CLS uses the standard session-window aggregation. Metrics are exposed via window.coreWebVitalsMetrics and browser CustomEvents (coreWebVitals:lcp, coreWebVitals:inp, coreWebVitals:cls) for custom dashboards.
Beyond measurement, Core Web Vitals adds resource hints (dns-prefetch, preconnect with crossorigin, prefetch), HTTP Server-Timing: php;dur=NN and Link preconnect headers (RFC 8288), X-DNS-Prefetch-Control: on, and preload plus font-display: swap for critical woff2 fonts to optimize LCP and eliminate FOIT-driven CLS. A cron task aggregates beacons into rolling 7-day and 30-day snapshots, with auto-pruning of stale samples and an admin opt-out switch.
- Hyva and Luma stores chasing the green “Good URLs” bucket in Search Console.
- Magento teams that need real-user INP data, not synthetic Lighthouse runs.
- Performance engineers tuning fonts, preconnect, and Server-Timing budgets.
What you get
Core Web Vitals Monitor tracks and optimizes real-user performance behavior:
- LCP, INP, CLS, FID, TTFB, and FCP via
PerformanceObserver. - Auto-dispatch to GA4 plus
sendBeaconto a custom endpoint. - Resource hints,
Server-Timing, and RFC 8288Linkpreconnect headers. - Font
preloadwithfont-display: swapto reduce FOIT and CLS. - Hourly cron with 7-day and 30-day rolling snapshots.
- Magento 2.4.4-2.4.9, PHP 8.1-8.4, Hyva and Luma compatible.
Magento 2 Core Web Vitals
Panth_CoreWebVitals collects Core Web Vitals (LCP, FID, INP and CLS) from real visitors of a Magento 2 storefront. When the module is enabled it renders an inline JavaScript snippet on every frontend page that registers PerformanceObserver listeners in the browser, rates each collected value, and optionally forwards the values to Google Analytics 4 and to a custom beacon endpoint. It also lets the administrator output resource hint link tags (dns-prefetch, preconnect, prefetch) and adds performance related HTTP headers (Server-Timing, X-DNS-Prefetch-Control, Link) to the response.
The module is aimed at merchants and developers who want field measurements of their store's Core Web Vitals without adding a third party library. It uses the standard head.additional block and before.body.end container and contains no theme specific code, so it works on both Hyva and Luma themes.
Product page: kishansavaliya.com/magento-2-corewebvitals.html
Features
- Collects LCP using the
largest-contentful-paintPerformanceObserver entry type (the last reported entry is used). - Collects FID using the
first-inputentry type. - Collects INP using the
evententry type with adurationThresholdof 16 ms; only entries with an interaction id count, and the worst interaction duration seen so far is kept. - Collects CLS using the
layout-shiftentry type, ignoring shifts that follow recent user input and aggregating shifts into session windows (gap under 1 s, window under 5 s). - Rates each value as
good,needs-improvementorpoorusing fixed thresholds (LCP 2500/4000 ms, FID 100/300 ms, INP 200/500 ms, CLS 0.1/0.25). - Sends each metric to GA4 through
gtag()whengtagis present on the page, with an optionalsend_tomeasurement ID. - Sends the final value of each metric as a JSON document to a custom endpoint through
navigator.sendBeaconwhen the page is hidden or left (again only if the value changed afterwards). - Dispatches a DOM
CustomEvent(coreWebVitals:lcp,coreWebVitals:fid,coreWebVitals:inp,coreWebVitals:cls) onwindowfor every collected metric. - Debug mode logs every metric to the browser console, exposes
window.coreWebVitalsMetrics, and prints a final summary when the page becomes hidden. - Outputs
<link rel="dns-prefetch">,<link rel="preconnect" crossorigin>and<link rel="prefetch">tags from admin configured lists. - Adds a
Server-Timingheader with the PHP execution time, anX-DNS-Prefetch-Control: onheader when DNS prefetch domains are configured, and aLink: <origin>; rel=preconnect; crossoriginheader for each preconnect domain. - Per metric enable switches; all settings are scoped to default, website and store view.
- Unit tests for the helper, plugin and observer under
Test/Unit.
Usage
Page output. With the module enabled, the frontend default.xml layout adds two blocks:
panth.corewebvitals.resource.hints(templateresource-hints.phtml) in thehead.additionalblock. It prints the dns-prefetch, preconnect and prefetch link tags, if any are configured, inside<head>.panth.corewebvitals.monitor(templatecore-web-vitals.phtml) in thebefore.body.endcontainer. It prints an inline<script>that reads a JSON configuration object built byHelper\Data::getConfigJson()and registers the PerformanceObserver listeners. The script exits immediately ifPerformanceObserveris not available in the browser.
Metric collection. Each metric is reported with a name (LCP, FID, INP, CLS), a numeric value (milliseconds, or a unitless score for CLS), a rating, an id, a delta and the observed entries. Values are rated against the thresholds published for Core Web Vitals (see web.dev), with the "good" boundary of each metric replaced by the configured target.
Reporting. When "Send Metrics to Analytics" is Yes:
- If
window.gtagexists, the script callsgtag('event', <metric name>, {...})withevent_category: 'Web Vitals',value(CLS multiplied by 1000 and rounded; other metrics rounded to whole milliseconds),event_label(the metric id),metric_ratingandnon_interaction: true. When a GA4 Measurement ID is configured it is added assend_to. - If a beacon URL is available, the script posts a JSON body with the fields
name,value,rating,id,delta,page(path and query string) andtimestampusingnavigator.sendBeacon. The URL comes from "Custom Beacon Endpoint URL"; if that is blank the script falls back towindow.panthCoreWebVitalsEndpointwhen a site defines it.
In addition, every metric dispatches window.dispatchEvent(new CustomEvent('coreWebVitals:<metric>', { detail })), so other scripts can listen with, for example, window.addEventListener('coreWebVitals:lcp', function (e) { console.log(e.detail); }).
Response headers. The plugin Plugin\AddPerformanceHeaders runs before Magento\Framework\App\Response\Http::sendResponse() and, when the module is enabled, sets:
Server-Timing: app;desc="PHP Execution";dur=<milliseconds since REQUEST_TIME_FLOAT>(appended to an existing Server-Timing value)X-DNS-Prefetch-Control: onwhen at least one DNS prefetch domain is configuredLink: <https://domain>; rel=preconnect; crossorigin, ...for the configured preconnect domains, appended to an existing Link header
The plugin is declared in etc/frontend/di.xml, so it only applies to storefront responses, not to the admin, REST, SOAP or GraphQL areas.
The module has no admin report pages, no scheduled cron jobs and no console commands. Collected metrics are not stored in Magento; they only exist in the browser and in whatever analytics destination is configured.
Documentation
USER_GUIDE.md is written for store administrators and covers installation, verifying that the module is active, every configuration field, what each metric means, resource hints, the performance HTTP headers, integrating with GA4 or a custom endpoint, and troubleshooting.
Changelog
See CHANGELOG.md.
Compatibility
| Platform | Versions |
|---|---|
| Magento Open Source | 2.4.4, 2.4.5, 2.4.6, 2.4.7, 2.4.8, 2.4.9 (as published on the product page) |
| Adobe Commerce | 2.4.4, 2.4.5, 2.4.6, 2.4.7, 2.4.8, 2.4.9 (as published on the product page) |
| PHP | 8.1, 8.2, 8.3, 8.4 (`~8.1.0 |
| Themes | Hyva and Luma |
Composer constraints on Magento packages: magento/framework ^103.0, magento/module-store ^101.0, magento/module-config ^101.0, magento/module-backend ^102.0.
Requirements
- Magento Open Source or Adobe Commerce 2.4.4 to 2.4.9.
- PHP 8.1, 8.2, 8.3 or 8.4.
mage2kishan/module-core^1.0(modulePanth_Core), which provides the "Panth Extensions" admin menu that this module attaches to. Composer installs it automatically.- No other packages are required or suggested by
composer.json.
Installation
composer require mage2kishan/module-corewebvitals
bin/magento module:enable Panth_Core Panth_CoreWebVitals
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
setup:di:compile is only needed when Magento runs in production mode. The module ships no files under view/*/web, so setup:static-content:deploy is not required for it.
Check that the module is active:
bin/magento module:status Panth_CoreWebVitals
Configuration
Admin path: Stores > Configuration > Panth Extensions > Core Web Vitals (section id panth_corewebvitals). All fields can be set at default, website and store view scope. The module is disabled by default; nothing is rendered and no headers are added until "Enable Module" is set to Yes.
General Settings
| Setting | Default | What it does |
|---|---|---|
| Enable Module | No | Master switch. Renders the monitoring snippet on frontend pages and activates the resource hints and response headers. All other fields depend on it. |
| Debug Mode | No | Logs collected metrics to the browser console and exposes window.coreWebVitalsMetrics. |
| Send Metrics to Analytics | Yes | Sends collected metrics to GA4 (when gtag exists on the page) and to the beacon endpoint below. |
| Custom Beacon Endpoint URL | (blank) | Absolute URL that receives a JSON POST through navigator.sendBeacon with the final value of each metric when the page is hidden or left. Blank skips the beacon. Shown only when "Send Metrics to Analytics" is Yes. |
| GA4 Measurement ID | (blank) | Optional G-XXXXXXX value used as the send_to parameter of the gtag() call. Shown only when "Send Metrics to Analytics" is Yes. |
Config paths: panth_corewebvitals/general/enabled, panth_corewebvitals/general/debug_mode, panth_corewebvitals/general/real_user_monitoring, panth_corewebvitals/general/endpoint_url, panth_corewebvitals/general/ga4_measurement_id.
LCP (Largest Contentful Paint) Monitoring
| Setting | Default | What it does |
|---|---|---|
| Monitor LCP | Yes | Registers the largest-contentful-paint observer. |
| Target LCP (milliseconds) | 2500 | Upper bound for a "good" LCP rating. Values above it and up to 4000 ms (or up to the target, if higher) are rated "needs-improvement"; anything slower is "poor". |
Config paths: panth_corewebvitals/lcp/enabled, panth_corewebvitals/lcp/target_lcp.
FID / INP (Interaction Responsiveness) Monitoring
| Setting | Default | What it does |
|---|---|---|
| Monitor FID and INP | Yes | Registers the first-input and event observers. |
| Target FID (milliseconds) | 100 | Upper bound for a "good" FID rating. The "poor" boundary stays at 300 ms unless the target is higher. |
| Target INP (milliseconds) | 200 | Upper bound for a "good" INP rating. The "poor" boundary stays at 500 ms unless the target is higher. |
Config paths: panth_corewebvitals/fid/enabled, panth_corewebvitals/fid/target_fid, panth_corewebvitals/fid/target_inp.
CLS (Cumulative Layout Shift) Monitoring
| Setting | Default | What it does |
|---|---|---|
| Monitor CLS | Yes | Registers the layout-shift observer. |
| Target CLS Score | 0.1 | Upper bound for a "good" CLS rating. The "poor" boundary stays at 0.25 unless the target is higher. |
Config paths: panth_corewebvitals/cls/enabled, panth_corewebvitals/cls/target_cls.
Resource Hints
| Setting | Default | What it does |
|---|---|---|
| DNS Prefetch Domains | (blank) | One domain per line without protocol. Each line becomes <link rel="dns-prefetch" href="//domain">; a line that already starts with http://, https:// or // is used as is. Also turns on the X-DNS-Prefetch-Control: on response header. |
| Preconnect Domains | (blank) | One domain per line without protocol. Each line is reduced to its origin (https:// is added when no scheme is given, paths are dropped, duplicates and invalid lines are skipped) and becomes <link rel="preconnect" href="https://domain" crossorigin> plus a Link: <https://domain>; rel=preconnect; crossorigin response header. |
| Prefetch URLs | (blank) | One full URL per line. Each line becomes <link rel="prefetch" href="url">. |
Config paths: panth_corewebvitals/resource_hints/dns_prefetch, panth_corewebvitals/resource_hints/preconnect, panth_corewebvitals/resource_hints/prefetch.
Blank lines and surrounding whitespace in the textarea fields are ignored.
Uninstallation
bin/magento module:disable Panth_CoreWebVitals
composer remove mage2kishan/module-corewebvitals
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
No database tables are created by the module, so nothing needs to be dropped. Saved configuration values under panth_corewebvitals/* remain in core_config_data and can be deleted manually if wanted. Remove Panth_Core only if no other Panth module depends on it.
License
Free and open source under the MIT License. See LICENSE.
Developer Notes
- Module name:
Panth_CoreWebVitals - Composer package:
mage2kishan/module-corewebvitals(version 1.0.11) - PHP namespace:
Panth\CoreWebVitals - Load sequence: after
Magento_Store,Magento_ConfigandPanth_Core - Key classes:
Helper\Datareads all configuration values at store scope (the current store unless a store id is passed) and builds the JSON configuration for the script (getConfigJson()).Block\CoreWebVitalsexposesisEnabled()andgetConfigJson()tocore-web-vitals.phtml.Block\ResourceHintsexposesisEnabled(),getDnsPrefetchDomains(),getPreconnectDomains()andgetPrefetchUrls()toresource-hints.phtml.Plugin\AddPerformanceHeaders::beforeSendResponse()adds the response headers (plugin namepanth_corewebvitals_performance_headers, sort order 10).- Extension points: the
coreWebVitals:*DOM events, thewindow.panthCoreWebVitalsEndpointglobal as a fallback beacon URL, and the two named layout blocks, which can be moved or removed in a theme'sdefault.xml. - ACL resources:
Panth_CoreWebVitals::corewebvitals("Core Web Vitals") andPanth_CoreWebVitals::config("Configuration"), both underMagento_Config::config. - Admin menu: "Core Web Vitals" > "Configuration" under the "Panth Extensions" menu provided by
Panth_Core, linking to the configuration section. - Database: the module ships no
db_schema.xmland creates no tables. - Translations:
i18n/en_US.csv.
| Module Category | Performance |
|---|---|
| Best For | Mid-Market |
Questions before you install?
Send me your composer.json and I will check for conflicts first. Free. Installation is +$45, custom work is quoted first.