{"id":"45ec5a38-559a-4d06-9239-e335c4fc7f26","shortId":"z2h666","kind":"skill","title":"cwv-audit","tagline":"Core Web Vitals Reference — LCP, INP, CLS thresholds, root causes, optimization fixes, CrUX BigQuery queries, web-vitals library usage, and SEO impact","description":"# Core Web Vitals Reference\n\nComplete technical reference for Core Web Vitals (LCP, INP, CLS): thresholds, common causes, fixes, measurement tools, CrUX BigQuery queries, web-vitals library setup, and SEO ranking impact.\n\nFull docs: https://cogny.com/docs/core-web-vitals\n\n## Usage\n\n```\n/cwv-audit                       # Full CWV overview and audit guidance\n/cwv-audit LCP                   # Deep-dive into LCP causes and fixes\n/cwv-audit INP                   # Deep-dive into INP causes and fixes\n/cwv-audit CLS                   # Deep-dive into CLS causes and fixes\n/cwv-audit CrUX competitor       # CrUX competitor comparison queries\n/cwv-audit monitoring            # GA4 + BigQuery monitoring setup\n/cwv-audit web-vitals            # web-vitals library integration guide\n```\n\n## Instructions\n\nYou are a Core Web Vitals performance expert. Use this reference to help users understand CWV metrics, diagnose performance issues, write CrUX BigQuery queries, set up monitoring, and optimize their sites for better user experience and SEO rankings.\n\nWhen the user asks a question, find the relevant section below and provide precise, actionable answers. If Search Console or GA4 MCP tools are available, use them to pull real data for the user's site.\n\nIf the user provides a specific metric or topic as an argument, focus on that area. Otherwise, provide an overview of all three vitals and their current thresholds.\n\n---\n\n## Overview\n\nCore Web Vitals (CWV) are three user-centric performance metrics that Google uses as ranking signals in Search. They measure loading performance, interactivity, and visual stability. Every page is assessed at the 75th percentile of real-user field data.\n\n| Metric | Full Name | Measures | Good | Needs Improvement | Poor |\n|--------|-----------|----------|------|--------------------|------|\n| **LCP** | Largest Contentful Paint | Loading performance | ≤ 2.5 s | ≤ 4.0 s | > 4.0 s |\n| **INP** | Interaction to Next Paint | Interactivity | ≤ 200 ms | ≤ 500 ms | > 500 ms |\n| **CLS** | Cumulative Layout Shift | Visual stability | ≤ 0.1 | ≤ 0.25 | > 0.25 |\n\nA page \"passes\" Core Web Vitals when all three metrics meet the \"Good\" threshold at the 75th percentile.\n\n---\n\n## LCP — Largest Contentful Paint\n\n### What It Measures\n\nLCP reports the render time of the largest image, video, or text block visible within the viewport, relative to when the page first started loading.\n\n### Thresholds\n\n- **Good:** ≤ 2.5 seconds\n- **Needs Improvement:** > 2.5 s and ≤ 4.0 s\n- **Poor:** > 4.0 seconds\n\n### LCP Candidate Elements\n\n- `<img>` elements (including inside `<picture>`)\n- `<image>` elements inside `<svg>`\n- `<video>` elements (poster image or first displayed frame)\n- Elements with `background-image` loaded via `url()` (not CSS gradients)\n- Block-level elements containing text nodes or inline-level text children\n\nThe largest element may change as the page loads. The final entry before user interaction is the LCP value.\n\n### Common Causes and Fixes\n\n**1. Slow server response time (TTFB)**\n- Use a CDN to serve content from edge locations\n- Cache HTML at the edge (stale-while-revalidate)\n- Pre-connect to required origins: `<link rel=\"preconnect\" href=\"https://cdn.example.com\">`\n- Use 103 Early Hints\n\n**2. Render-blocking resources**\n- Inline critical CSS, defer non-critical stylesheets\n- Defer or async non-critical JavaScript: `<script defer src=\"app.js\">`\n- Minimize CSS size, avoid `@import` in CSS\n\n**3. Slow resource load times**\n- Preload the LCP image: `<link rel=\"preload\" as=\"image\" href=\"hero.webp\">`\n- Use modern formats (WebP, AVIF) with `<picture>` fallbacks\n- Set `fetchpriority=\"high\"` on the LCP `<img>`\n- Use responsive images with `srcset` and `sizes`\n\n**4. Client-side rendering delay**\n- SSR or SSG the LCP content\n- Pre-render critical routes\n- Reduce JavaScript bundle size\n\n**5. Web font blocking LCP text**\n- Use `font-display: swap` or `font-display: optional`\n- Preload the primary font file\n- Subset fonts to required characters\n\n---\n\n## INP — Interaction to Next Paint\n\n### What It Measures\n\nINP measures the latency of all click, tap, and keyboard interactions throughout the page lifecycle, and reports a single value representing the worst-case interaction. It replaced FID as a Core Web Vital in March 2024.\n\n### Thresholds\n\n- **Good:** ≤ 200 milliseconds\n- **Needs Improvement:** > 200 ms and ≤ 500 ms\n- **Poor:** > 500 milliseconds\n\n### How It Differs from FID\n\n| | FID | INP |\n|---|-----|-----|\n| **Scope** | First interaction only | All interactions |\n| **What it measures** | Input delay only | Full latency: input delay + processing + presentation delay |\n| **Status** | Deprecated (March 2024) | Official Core Web Vital |\n\n### Three Phases of Interaction Latency\n\n1. **Input delay** — time from user action to event handler start\n2. **Processing time** — time spent running event handlers\n3. **Presentation delay** — time from handler completion to next paint\n\n### Common Causes and Fixes\n\n**1. Long tasks blocking the main thread**\n- Break up long tasks using `scheduler.yield()` or `setTimeout(0)`\n- Use `requestIdleCallback` for non-urgent work\n- Move heavy computation to Web Workers\n\n**2. Heavy JavaScript execution**\n- Code-split with dynamic `import()`\n- Tree-shake unused exports at build time\n- Defer non-critical scripts and third-party tags\n\n**3. Expensive event handlers**\n- Debounce or throttle rapid-fire handlers\n- Avoid forced synchronous layouts in handlers\n- Use `content-visibility: auto` for off-screen content\n\n**4. Large DOM and expensive rendering**\n- Virtualize long lists (react-window, @tanstack/virtual)\n- Use CSS `contain: layout style paint`\n- Reduce DOM depth and element count\n\n**5. Excessive re-renders in SPA frameworks**\n- Memoize components (`React.memo`, `useMemo`)\n- Use `startTransition` for non-urgent state updates\n\n---\n\n## CLS — Cumulative Layout Shift\n\n### What It Measures\n\nCLS measures the sum of unexpected layout shift scores during the page lifespan. A layout shift occurs when a visible element changes position without being triggered by user interaction.\n\n### Thresholds\n\n- **Good:** ≤ 0.1\n- **Needs Improvement:** > 0.1 and ≤ 0.25\n- **Poor:** > 0.25\n\n### Session Window Calculation\n\n1. Shifts are grouped into session windows (max 5 seconds, 1-second gap ends a window)\n2. CLS = the maximum session window score\n3. Each shift score = impact fraction x distance fraction\n\n### What Counts as a Layout Shift\n\n- Position changes NOT triggered by user input\n- CSS `transform` animations do NOT count\n- Shifts within 500ms of user interaction are excluded\n\n### Common Causes and Fixes\n\n**1. Images/videos without dimensions**\n\n```html\n<!-- GOOD -->\n<img src=\"hero.jpg\" alt=\"Hero\" width=\"800\" height=\"400\">\n<!-- Or use CSS aspect-ratio -->\n<style>.hero-img { aspect-ratio: 16 / 9; width: 100%; }</style>\n```\n\n**2. Dynamically injected content**\n\n```css\n.ad-slot { min-height: 250px; min-width: 300px; contain: layout style paint; }\n```\n\n**3. Web fonts causing FOIT/FOUT**\n\n```css\n@font-face {\n  font-family: 'Custom Font';\n  src: url('custom.woff2') format('woff2');\n  font-display: optional; /* eliminates layout shift entirely */\n}\n```\n\n**4. Ads/embeds without reserved space**\n\n```css\n.embed-container {\n  position: relative;\n  padding-bottom: 56.25%; /* 16:9 */\n  height: 0; overflow: hidden;\n}\n.embed-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }\n```\n\n**5. Late-loading banners/cookie bars**\n- Use `position: fixed` or `sticky` so they overlay without shifting content\n\n---\n\n## Measurement Tools\n\n### Field Data (Real Users)\n\n| Tool | Description |\n|------|-------------|\n| **CrUX** | 28-day rolling data via BigQuery, API, and PageSpeed Insights |\n| **Search Console CWV report** | Groups URLs by Good/Needs Improvement/Poor |\n| **PageSpeed Insights (field section)** | CrUX 75th percentile values per URL/origin |\n| **web-vitals library** | Measures CWV in real browsers, send to any endpoint |\n\n### Lab Data (Synthetic)\n\n| Tool | Description |\n|------|-------------|\n| **Lighthouse** | Simulated LCP and CLS (not INP) |\n| **Chrome DevTools Performance panel** | Full flame charts for all three metrics |\n| **WebPageTest** | Multi-step tests with filmstrips and waterfalls |\n\n**Important:** Lab tools cannot fully measure INP. Always validate with field data.\n\n### JavaScript APIs\n\n```javascript\n// Observe LCP\nnew PerformanceObserver((list) => {\n  const entries = list.getEntries();\n  console.log('LCP:', entries[entries.length - 1].startTime);\n}).observe({ type: 'largest-contentful-paint', buffered: true });\n\n// Observe CLS\nnew PerformanceObserver((list) => {\n  for (const entry of list.getEntries()) {\n    if (!entry.hadRecentInput) console.log('Shift:', entry.value);\n  }\n}).observe({ type: 'layout-shift', buffered: true });\n\n// Observe INP (Event Timing API)\nnew PerformanceObserver((list) => {\n  for (const entry of list.getEntries()) {\n    if (entry.interactionId) console.log('Interaction:', entry.duration, 'ms');\n  }\n}).observe({ type: 'event', buffered: true, durationThreshold: 16 });\n```\n\n---\n\n## web-vitals Library\n\n### Installation\n\n```bash\nnpm install web-vitals\n```\n\n### Basic Usage\n\n```javascript\nimport { onLCP, onINP, onCLS } from 'web-vitals';\nonLCP(console.log);\nonINP(console.log);\nonCLS(console.log);\n```\n\n### Send to GA4\n\n```javascript\nimport { onLCP, onINP, onCLS } from 'web-vitals';\n\nfunction sendToGA4(metric) {\n  gtag('event', metric.name, {\n    value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),\n    event_category: 'Web Vitals',\n    event_label: metric.id,\n    non_interaction: true,\n  });\n}\n\nonLCP(sendToGA4);\nonINP(sendToGA4);\nonCLS(sendToGA4);\n```\n\n### Send to Custom Endpoint\n\n```javascript\nimport { onLCP, onINP, onCLS } from 'web-vitals';\n\nfunction sendToAnalytics(metric) {\n  const body = JSON.stringify({\n    name: metric.name, value: metric.value, rating: metric.rating,\n    delta: metric.delta, id: metric.id, page: window.location.pathname,\n  });\n  if (navigator.sendBeacon) navigator.sendBeacon('/api/vitals', body);\n  else fetch('/api/vitals', { body, method: 'POST', keepalive: true });\n}\n\nonLCP(sendToAnalytics);\nonINP(sendToAnalytics);\nonCLS(sendToAnalytics);\n```\n\n### Attribution Builds\n\n```javascript\nimport { onLCP, onINP, onCLS } from 'web-vitals/attribution';\n\nonLCP((metric) => {\n  console.log('LCP element:', metric.attribution.element);\n  console.log('TTFB:', metric.attribution.timeToFirstByte);\n  console.log('Resource load delay:', metric.attribution.resourceLoadDelay);\n  console.log('Element render delay:', metric.attribution.elementRenderDelay);\n});\n\nonINP((metric) => {\n  console.log('Target:', metric.attribution.interactionTarget);\n  console.log('Input delay:', metric.attribution.inputDelay);\n  console.log('Processing:', metric.attribution.processingDuration);\n  console.log('Presentation delay:', metric.attribution.presentationDelay);\n});\n\nonCLS((metric) => {\n  console.log('Largest shift target:', metric.attribution.largestShiftTarget);\n  console.log('Largest shift value:', metric.attribution.largestShiftValue);\n  console.log('Load state:', metric.attribution.loadState);\n});\n```\n\n---\n\n## CrUX BigQuery Queries\n\n### CWV Scores by Origin\n\n```sql\nSELECT\n  origin,\n  form_factor.name AS device,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(lcp.start < 2500, lcp.density, 0)), SUM(lcp.density)\n  ), 4) AS lcp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(inp.start < 200, inp.density, 0)), SUM(inp.density)\n  ), 4) AS inp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(cls.start < 0.1, cls.density, 0)), SUM(cls.density)\n  ), 4) AS cls_good_pct\nFROM `chrome-ux-report.all.202501`,\n  UNNEST(largest_contentful_paint.histogram.bin) AS lcp,\n  UNNEST(interaction_to_next_paint.histogram.bin) AS inp,\n  UNNEST(cumulative_layout_shift.histogram.bin) AS cls\nWHERE origin = 'https://www.example.com'\nGROUP BY origin, device\nORDER BY device\n```\n\n### CWV by Page Type (URL-level)\n\n```sql\nSELECT\n  url,\n  form_factor.name AS device,\n  ROUND(p75_lcp / 1000, 2) AS p75_lcp_sec,\n  p75_inp AS p75_inp_ms,\n  ROUND(p75_cls, 3) AS p75_cls\nFROM `chrome-ux-report.materialized.device_summary`\nWHERE origin = 'https://www.example.com'\n  AND url LIKE '%/product/%'\n  AND date = (SELECT MAX(date) FROM `chrome-ux-report.materialized.device_summary`)\nORDER BY p75_lcp DESC\nLIMIT 50\n```\n\n### Trending CWV Over Time\n\n```sql\nSELECT\n  yyyymm,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(lcp.start < 2500, lcp.density, 0)), SUM(lcp.density)\n  ), 4) AS lcp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(inp.start < 200, inp.density, 0)), SUM(inp.density)\n  ), 4) AS inp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(cls.start < 0.1, cls.density, 0)), SUM(cls.density)\n  ), 4) AS cls_good_pct\nFROM `chrome-ux-report.all.*`,\n  UNNEST(largest_contentful_paint.histogram.bin) AS lcp,\n  UNNEST(interaction_to_next_paint.histogram.bin) AS inp,\n  UNNEST(cumulative_layout_shift.histogram.bin) AS cls\nWHERE origin = 'https://www.example.com'\n  AND _TABLE_SUFFIX BETWEEN '202401' AND '202501'\n  AND form_factor.name = 'phone'\nGROUP BY yyyymm\nORDER BY yyyymm\n```\n\n### Competitor Comparison\n\n```sql\nWITH origins AS (\n  SELECT origin FROM UNNEST([\n    'https://www.yoursite.com',\n    'https://www.competitor-a.com',\n    'https://www.competitor-b.com'\n  ]) AS origin\n)\nSELECT\n  o.origin, form_factor.name AS device,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(lcp.start < 2500, lcp.density, 0)), SUM(lcp.density)\n  ), 4) AS lcp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(inp.start < 200, inp.density, 0)), SUM(inp.density)\n  ), 4) AS inp_good_pct,\n  ROUND(SAFE_DIVIDE(\n    SUM(IF(cls.start < 0.1, cls.density, 0)), SUM(cls.density)\n  ), 4) AS cls_good_pct\nFROM origins o\nINNER JOIN `chrome-ux-report.all.202501` crux ON crux.origin = o.origin,\n  UNNEST(largest_contentful_paint.histogram.bin) AS lcp,\n  UNNEST(interaction_to_next_paint.histogram.bin) AS inp,\n  UNNEST(cumulative_layout_shift.histogram.bin) AS cls\nWHERE form_factor.name = 'phone'\nGROUP BY o.origin, device\nORDER BY o.origin, device\n```\n\n---\n\n## SEO Impact\n\n### Page Experience Ranking Signal\n\nCWV are part of Google's page experience signals alongside HTTPS, mobile-friendliness, and no intrusive interstitials.\n\n- CWV act as a **tiebreaker** — when relevance and quality are equal, better CWV may rank higher\n- CWV are **not a dominant signal** — they do not override strong content or backlinks\n- Google uses **field data from CrUX** at the 75th percentile (not lab scores)\n- **Mobile CWV** affect mobile rankings; **desktop CWV** affect desktop rankings\n\n### Optimization Priority\n\nOptimize for mobile first — it typically has the strictest constraints due to lower processing power and slower networks.\n\n---\n\n## Optimization Patterns\n\n### Image Optimization\n\n```html\n<picture>\n  <source srcset=\"hero.avif\" type=\"image/avif\">\n  <source srcset=\"hero.webp\" type=\"image/webp\">\n  <img src=\"hero.jpg\" alt=\"Hero\" width=\"1200\" height=\"600\"\n       fetchpriority=\"high\" decoding=\"async\">\n</picture>\n\n<!-- Responsive images -->\n<img src=\"hero-800.webp\" alt=\"Hero\"\n     srcset=\"hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w\"\n     sizes=\"(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px\"\n     loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"600\">\n```\n\n**Key rule:** Never lazy-load the LCP image. Set `fetchpriority=\"high\"` on it instead.\n\n### Font Optimization\n\n```html\n<link rel=\"preload\" as=\"font\" type=\"font/woff2\" href=\"/fonts/main.woff2\" crossorigin>\n```\n\n```css\n@font-face {\n  font-family: 'Main Font';\n  src: url('/fonts/main.woff2') format('woff2');\n  font-display: swap;\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153;\n}\n```\n\n### JavaScript Optimization\n\n```html\n<script defer src=\"/js/app.js\"></script>\n<script async src=\"https://analytics.example.com/tag.js\"></script>\n```\n\n```javascript\n// Dynamic import for code splitting\nconst Chart = await import('./components/Chart.js');\n\n// Non-urgent work\nrequestIdleCallback(() => { initializeAnalytics(); });\n```\n\n### CSS Optimization\n\n```css\n/* Limit recalculation scope */\n.card { contain: layout style paint; }\n\n/* Skip rendering off-screen content */\n.below-fold { content-visibility: auto; contain-intrinsic-size: 0 500px; }\n```\n\n### Third-Party Script Management\n\n- Load non-critical third-party scripts after `window.load`\n- Use `<link rel=\"preconnect\">` for required third-party origins\n- Use server-side tagging where possible\n- Audit third-party impact with Chrome DevTools Coverage tab\n\n---\n\n## GA4 + BigQuery Monitoring Setup\n\n### Send CWV to GA4\n\n```javascript\nimport { onLCP, onINP, onCLS } from 'web-vitals/attribution';\n\nfunction sendToGA4(metric) {\n  gtag('event', metric.name, {\n    value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),\n    event_category: 'Web Vitals',\n    event_label: metric.id,\n    metric_rating: metric.rating,\n    debug_target: metric.attribution?.interactionTarget\n      || metric.attribution?.element\n      || metric.attribution?.largestShiftTarget\n      || '(not set)',\n    non_interaction: true,\n  });\n}\n\nonLCP(sendToGA4);\nonINP(sendToGA4);\nonCLS(sendToGA4);\n```\n\n### Query CWV from GA4 BigQuery Export\n\n```sql\nWITH vitals AS (\n  SELECT\n    DATE(TIMESTAMP_MICROS(event_timestamp)) AS date,\n    event_name AS metric_name,\n    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'value') AS metric_value,\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_rating') AS rating,\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'debug_target') AS debug_target,\n    device.category AS device_type\n  FROM `project.analytics_123456789.events_*`\n  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY))\n                          AND FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)\n    AND event_name IN ('LCP', 'INP', 'CLS')\n)\nSELECT\n  date, metric_name, device_type,\n  COUNT(*) AS samples,\n  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS p75,\n  COUNTIF(rating = 'good') / COUNT(*) AS good_pct,\n  COUNTIF(rating = 'poor') / COUNT(*) AS poor_pct\nFROM vitals\nGROUP BY date, metric_name, device_type\nORDER BY date DESC, metric_name, device_type\n```\n\n### Identify Worst Pages\n\n```sql\nWITH page_vitals AS (\n  SELECT\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page,\n    event_name AS metric_name,\n    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'value') AS metric_value,\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_rating') AS rating,\n    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'debug_target') AS debug_target\n  FROM `project.analytics_123456789.events_*`\n  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY))\n                          AND FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)\n    AND event_name IN ('LCP', 'INP', 'CLS')\n)\nSELECT\n  REGEXP_EXTRACT(page, r'^https?://[^/]+(/.*)') AS path,\n  metric_name,\n  COUNT(*) AS samples,\n  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS p75,\n  COUNTIF(rating = 'poor') / COUNT(*) AS poor_pct,\n  APPROX_TOP_COUNT(debug_target, 3) AS top_debug_targets\nFROM page_vitals\nWHERE page IS NOT NULL\nGROUP BY path, metric_name\nHAVING samples >= 50\nORDER BY poor_pct DESC\nLIMIT 50\n```\n\n## Resources\n\n- **web.dev Core Web Vitals:** https://web.dev/articles/vitals\n- **CrUX documentation:** https://developer.chrome.com/docs/crux/\n- **web-vitals library:** https://github.com/GoogleChrome/web-vitals\n- **CrUX BigQuery cookbook:** https://developer.chrome.com/docs/crux/bigquery/\n- **PageSpeed Insights:** https://pagespeed.web.dev/\n- **Full Cogny Docs:** https://cogny.com/docs/core-web-vitals","tags":["cwv","audit","claude","code","marketing","skills","cognyai","agent-skills","ai-agents","claude-code","claude-skills","cluade-mcp"],"capabilities":["skill","source-cognyai","skill-cwv-audit","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-claude-skills","topic-cluade-mcp","topic-cursor","topic-geo","topic-growth-hacking","topic-llm","topic-marketing","topic-mcp","topic-seo"],"categories":["claude-code-marketing-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cognyai/claude-code-marketing-skills/cwv-audit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cognyai/claude-code-marketing-skills","source_repo":"https://github.com/cognyai/claude-code-marketing-skills","install_from":"skills.sh"}},"qualityScore":"0.471","qualityRationale":"deterministic score 0.47 from registry signals: · indexed on github topic:agent-skills · 42 github stars · SKILL.md body (19,664 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-01T06:56:25.982Z","embedding":null,"createdAt":"2026-04-18T22:23:32.086Z","updatedAt":"2026-05-01T06:56:25.982Z","lastSeenAt":"2026-05-01T06:56:25.982Z","tsv":"'+0000':1418 '+0131':1422 '+0152':1424 '-00':1419 '-0153':1425 '/api/vitals':861,865 '/articles/vitals':1895 '/attribution':888,1532 '/components/chart.js':1439 '/cwv-audit':65,72,82,92,102,109,115 '/docs/core-web-vitals':63,1922 '/docs/crux/':1900 '/docs/crux/bigquery/':1913 '/fonts/main.woff2':1407 '/googlechrome/web-vitals':1907 '/product':1070 '0':556,566,568,961,977,993,1101,1117,1133,1202,1218,1234,1474 '0.1':308,991,1131,1232 '0.25':309,310 '1':437,700,1668,1818 '100':570,572,1689,1843 '1000':809,1042,1544 '103':468 '16':553,757 '2':471,491,1043 '2.5':284,363,367 '200':296,975,1115,1216 '202401':1162 '202501':1003,1164,1248 '2500':959,1099,1200 '250px':502 '28':599,1658,1808 '3':511,1057,1860 '300px':506 '4':538,964,980,996,1104,1120,1136,1205,1221,1237 '4.0':286,288,370,373 '5':573 '50':1085,1880,1887 '500':298,300 '500px':1475 '56.25':552 '75':1691,1845 '75th':262,327,623,1338 '9':554 'absolut':564 'act':1301 'action':178 'ad':497 'ad-slot':496 'ads/embeds':539 'affect':1345,1350 'alongsid':1291 'alway':680 'answer':179 'api':605,686,736 'approx':1685,1839,1855 'area':215 'argument':211 'ask':167 'assess':259 'async':486 'attribut':877 'audit':3,70,1505 'auto':1469 'avail':188 'await':1437 'background':393 'background-imag':392 'backlink':1329 'banners/cookie':577 'bar':578 'bash':763 'basic':769 'below-fold':1463 'better':158,1311 'bigqueri':17,48,112,148,604,941,1516,1579,1909 'block':348,402,474 'block-level':401 'bodi':844,862,866 'bottom':551 'browser':636 'buffer':708,730,754 'build':878 'cach':452 'candid':376 'cannot':676 'card':1452 'categori':812,1547 'caus':13,43,79,89,99,434,514 'cdn':445 'centric':237 'chang':418 'chart':659,1436 'children':413 'chrome':653,1511 'chrome-ux-report.all':1002,1142,1247 'chrome-ux-report.materialized.device':1062,1077 'cls':10,40,93,98,302,650,711,807,998,1015,1056,1060,1138,1154,1239,1264,1542,1675,1825 'cls.density':992,995,1132,1135,1233,1236 'cls.start':990,1130,1231 'code':1433 'cogni':1918 'cogny.com':62,1921 'cogny.com/docs/core-web-vitals':61,1920 'common':42,433 'comparison':107,1175 'competitor':104,106,1174 'complet':31 'connect':463 'consol':182,610 'console.log':696,722,747,781,783,785,891,895,898,903,910,913,917,920,926,931,936 'const':693,716,741,843,1435 'constraint':1364 'contain':405,507,546,561,1453,1471 'contain-intrinsic-s':1470 'content':280,331,448,494,589,706,1327,1462,1467 'content-vis':1466 'cookbook':1910 'core':4,27,35,129,229,314,1890 'count':1682,1697,1704,1836,1851,1857 'countif':1694,1701,1848 'coverag':1513 'critic':477,482,489,1484 'crux':16,47,103,105,147,598,622,940,1249,1335,1896,1908 'crux.origin':1251 'css':399,478,495,516,543,1396,1446,1448 'cumul':303 'cumulative_layout_shift.histogram.bin':1013,1152,1262 'current':226,1655,1666,1805,1816 'custom':523,829 'custom.woff2':527 'cwv':2,67,141,232,611,633,943,1026,1087,1282,1300,1312,1316,1344,1349,1520,1576 'cwv-audit':1 'd':1652,1665,1802,1815 'data':194,269,593,602,642,684,1333 'date':1072,1075,1586,1592,1649,1653,1656,1662,1667,1677,1712,1719,1799,1803,1806,1812,1817 'day':600,1659,1809 'debug':1556,1633,1636,1787,1790,1858,1863 'deep':75,85,95 'deep-div':74,84,94 'defer':479,484 'delay':901,906,915,922 'delta':852 'desc':1083,1720,1885 'descript':597,645 'desktop':1348,1351 'developer.chrome.com':1899,1912 'developer.chrome.com/docs/crux/':1898 'developer.chrome.com/docs/crux/bigquery/':1911 'devic':952,1022,1025,1038,1193,1271,1275,1640,1680,1715,1723 'device.category':1638 'devtool':654,1512 'diagnos':143 'display':388,532,1412 'dive':76,86,96 'divid':955,971,987,1095,1111,1127,1196,1212,1228 'doc':60,1919 'document':1897 'domin':1320 'due':1365 'durationthreshold':756 'dynam':492,1430 'earli':469 'edg':450,456 'element':377,378,381,383,390,404,416,893,904,1561 'elimin':534 'els':863 'emb':545,560 'embed-contain':544,559 'endpoint':640,830 'entir':537 'entri':425,694,698,717,742 'entries.length':699 'entry.duration':749 'entry.hadrecentinput':721 'entry.interactionid':746 'entry.value':724 'equal':1310 'event':734,753,802,811,815,1537,1546,1550,1589,1593,1603,1616,1629,1670,1739,1747,1757,1770,1783,1820 'everi':256 'experi':160,1279,1289 'expert':133 'export':1580 'extract':1828 'face':519,1399 'famili':522,1402 'fetch':864 'fetchprior':1388 'ff':1420 'field':268,592,620,683,1332 'filmstrip':670 'final':424 'find':170 'first':358,387,1358 'fix':15,44,81,91,101,436,581 'flame':658 'focus':212 'foit/fout':515 'fold':1465 'font':513,518,521,524,531,1393,1398,1401,1404,1411 'font-display':530,1410 'font-fac':517,1397 'font-famili':520,1400 'form_factor.name':950,1036,1166,1191,1266 'format':528,1408,1648,1661,1798,1811 'frame':389 'friendli':1295 'full':59,66,271,657,1917 'fulli':677 'function':798,840,1533 'ga4':111,184,788,1515,1522,1578 'github.com':1906 'github.com/googlechrome/web-vitals':1905 'good':274,323,362,967,983,999,1107,1123,1139,1208,1224,1240,1696,1699 'good/needs':616 'googl':241,1286,1330 'gradient':400 'group':613,1019,1168,1268,1710,1873 'gtag':801,1536 'guid':124 'guidanc':71 'height':501,555,571 'help':138 'hidden':558 'high':1389 'higher':1315 'hint':470 'html':453,1377,1395,1428 'https':1292,1831 'id':854 'identifi':1725 'ifram':562 'imag':344,385,394,1375,1386 'impact':26,58,1277,1509 'import':673,772,790,832,880,1431,1438,1524 'improv':276,366 'improvement/poor':617 'includ':379 'initializeanalyt':1445 'inject':493 'inlin':410,476 'inline-level':409 'inner':1245 'inp':9,39,83,88,290,652,679,733,982,1011,1049,1052,1122,1150,1223,1260,1674,1824 'inp.density':976,979,1116,1119,1217,1220 'inp.start':974,1114,1215 'input':914 'insid':380,382 'insight':608,619,1915 'instal':762,765 'instead':1392 'instruct':125 'integr':123 'interact':252,291,295,428,748,819,1567 'interaction_to_next_paint.histogram.bin':1009,1148,1258 'interactiontarget':1559 'interstiti':1299 'interv':1657,1807 'intrins':1472 'intrus':1298 'issu':145 'javascript':490,685,687,771,789,831,879,1426,1429,1523 'join':1246 'json.stringify':845 'keepal':869 'key':1378,1606,1619,1632,1742,1760,1773,1786 'lab':641,674,1341 'label':816,1551 'largest':279,330,343,415,705,927,932 'largest-contentful-paint':704 'largest_contentful_paint.histogram.bin':1005,1144,1254 'largestshifttarget':1563 'late':575 'late-load':574 'layout':304,508,535,728,1454 'layout-shift':727 'lazi':1382 'lazy-load':1381 'lcp':8,38,73,78,278,329,336,375,431,648,689,697,892,966,1007,1041,1046,1082,1106,1146,1207,1256,1385,1673,1823 'lcp.density':960,963,1100,1103,1201,1204 'lcp.start':958,1098,1199 'left':567 'level':403,411,1032 'librari':22,53,122,631,761,1904 'lighthous':646 'like':1069 'limit':1084,1449,1886 'list':692,714,739 'list.getentries':695,719,744 'load':250,282,360,395,422,576,900,937,1383,1481 'locat':451,1744 'lower':1367 'm':1651,1664,1801,1814 'main':1403 'manag':1480 'math.round':805,1540 'max':1074 'may':417,1313 'mcp':185 'measur':45,249,273,335,590,632,678 'meet':321 'method':867 'metric':142,206,239,270,320,663,800,842,890,909,925,1535,1553,1596,1609,1620,1678,1687,1713,1721,1750,1763,1774,1834,1841,1876 'metric.attribution':1558,1560,1562 'metric.attribution.element':894 'metric.attribution.elementrenderdelay':907 'metric.attribution.inputdelay':916 'metric.attribution.interactiontarget':912 'metric.attribution.largestshifttarget':930 'metric.attribution.largestshiftvalue':935 'metric.attribution.loadstate':939 'metric.attribution.presentationdelay':923 'metric.attribution.processingduration':919 'metric.attribution.resourceloaddelay':902 'metric.attribution.timetofirstbyte':897 'metric.delta':853 'metric.id':817,855,1552 'metric.name':803,806,847,1538,1541 'metric.rating':851,1555 'metric.value':808,810,849,1543,1545 'micro':1588 'min':500,504 'min-height':499 'min-width':503 'mobil':1294,1343,1346,1357 'mobile-friendli':1293 'monitor':110,113,152,1517 'ms':297,299,301,750,1053 'multi':666 'multi-step':665 'name':272,846,1594,1597,1671,1679,1714,1722,1748,1751,1821,1835,1877 'navigator.sendbeacon':859,860 'need':275,365 'network':1372 'never':1380 'new':690,712,737 'next':293 'node':407 'non':481,488,818,1441,1483,1566 'non-crit':480,487,1482 'non-urg':1440 'npm':764 'null':1872 'o':1244 'o.origin':1190,1252,1270,1274 'observ':688,702,710,725,732,751 'off-screen':1459 'offset':1690,1844 'oncl':775,784,793,825,835,875,883,924,1527,1573 'oninp':774,782,792,823,834,873,882,908,1526,1571 'onlcp':773,780,791,821,833,871,881,889,1525,1569 'optim':14,154,1353,1355,1373,1376,1394,1427,1447 'option':533 'order':1023,1079,1171,1272,1717,1881 'origin':466,946,949,1017,1021,1065,1156,1178,1181,1188,1243,1497 'otherwis':216 'overflow':557 'overlay':586 'overrid':1325 'overview':68,219,228 'p75':1040,1045,1048,1051,1055,1059,1081,1693,1847 'pad':550 'padding-bottom':549 'page':257,312,357,421,856,1028,1278,1288,1727,1730,1743,1746,1829,1866,1869 'pagespe':607,618,1914 'pagespeed.web.dev':1916 'paint':281,294,332,510,707,1456 'panel':656 'param':1604,1617,1630,1740,1758,1771,1784 'part':1284 'parti':1478,1487,1496,1508 'pass':313 'path':1833,1875 'pattern':1374 'pct':968,984,1000,1108,1124,1140,1209,1225,1241,1700,1707,1854,1884 'per':626 'percentil':263,328,624,1339 'perform':132,144,238,251,283,655 'performanceobserv':691,713,738 'phone':1167,1267 'poor':277,372,1703,1706,1850,1853,1883 'posit':547,563,580 'possibl':1504 'post':868 'poster':384 'power':1369 'pre':462 'pre-connect':461 'precis':177 'present':921 'prioriti':1354 'process':918,1368 'project.analytics_123456789.events':1643,1793 'provid':176,203,217 'pull':192 'qualiti':1308 'quantil':1686,1840 'queri':18,49,108,149,942,1575 'question':169 'r':1830 'rang':1416 'rank':57,163,244,1280,1314,1347,1352 'rate':850,1554,1621,1623,1695,1702,1775,1777,1849 'real':193,266,594,635 'real-us':265 'recalcul':1450 'refer':7,30,33,136 'regexp':1827 'relat':353,548 'relev':172,1306 'render':339,473,905,1458 'render-block':472 'report':337,612 'requestidlecallback':1444 'requir':465,1493 'reserv':541 'resourc':475,899,1888 'respons':440 'revalid':460 'roll':601 'root':12 'round':953,969,985,1039,1054,1093,1109,1125,1194,1210,1226 'rule':1379 'safe':954,970,986,1094,1110,1126,1195,1211,1227 'sampl':1684,1838,1879 'scope':1451 'score':944,1342 'screen':1461 'script':1479,1488 'search':181,247,609 'sec':1047 'second':364,374 'section':173,621 'select':948,1034,1073,1091,1180,1189,1585,1598,1611,1624,1676,1733,1734,1752,1765,1778,1826 'send':637,786,827,1519 'sendtoanalyt':841,872,874,876 'sendtoga4':799,822,824,826,1534,1570,1572,1574 'seo':25,56,162,1276 'serv':447 'server':439,1500 'server-sid':1499 'set':150,1387,1565 'setup':54,114,1518 'shift':305,536,588,723,729,928,933 'side':1501 'signal':245,1281,1290,1321 'simul':647 'site':156,199 'size':1473 'skill' 'skill-cwv-audit' 'skip':1457 'slot':498 'slow':438 'slower':1371 'source-cognyai' 'space':542 'specif':205 'split':1434 'sql':947,1033,1090,1176,1581,1728 'src':525,1405 'stabil':255,307 'stale':458 'stale-while-revalid':457 'start':359 'starttim':701 'state':938 'step':667 'sticki':583 'strictest':1363 'strong':1326 'style':509,1455 'stylesheet':483 'sub':1654,1804 'suffix':1160,1646,1796 'sum':956,962,972,978,988,994,1096,1102,1112,1118,1128,1134,1197,1203,1213,1219,1229,1235 'summari':1063,1078 'swap':1413 'synthet':643 'tab':1514 'tabl':1159,1645,1795 'tag':1502 'target':911,929,1557,1634,1637,1788,1791,1859,1864 'technic':32 'test':668 'text':347,406,412 'third':1477,1486,1495,1507 'third-parti':1476,1485,1494,1506 'three':222,234,319,662 'threshold':11,41,227,324,361 'tiebreak':1304 'time':340,441,735,1089 'timestamp':1587,1590 'tool':46,186,591,596,644,675 'top':565,1856,1862 'topic':208 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-claude-skills' 'topic-cluade-mcp' 'topic-cursor' 'topic-geo' 'topic-growth-hacking' 'topic-llm' 'topic-marketing' 'topic-mcp' 'topic-seo' 'trend':1086 'true':709,731,755,820,870,1568 'ttfb':442,896 'type':703,726,752,1029,1641,1681,1716,1724 'typic':1360 'u':1417,1421,1423 'understand':140 'unicod':1415 'unicode-rang':1414 'unnest':1004,1008,1012,1143,1147,1151,1183,1253,1257,1261,1602,1615,1628,1738,1756,1769,1782 'urgent':1442 'url':397,526,614,1031,1035,1068,1406 'url-level':1030 'url/origin':627 'usag':23,64,770 'use':134,189,242,443,467,579,1331,1491,1498 'user':139,159,166,197,202,236,267,427,595 'user-centr':235 'valid':681 'valu':432,625,804,848,934,1539,1600,1607,1610,1613,1626,1688,1736,1754,1761,1764,1767,1780,1842 'value.int':1599,1753 'value.string':1612,1625,1735,1766,1779 'via':396,603 'video':345 'viewport':352 'visibl':349,1468 'visual':254,306 'vital':6,21,29,37,52,118,121,131,223,231,316,630,760,768,779,797,814,839,887,1531,1549,1583,1709,1731,1867,1892,1903 'waterfal':672 'web':5,20,28,36,51,117,120,130,230,315,512,629,759,767,778,796,813,838,886,1530,1548,1891,1902 'web-vit':19,50,116,119,628,758,766,777,795,837,885,1529,1901 'web.dev':1889,1894 'web.dev/articles/vitals':1893 'webpagetest':664 'width':505,569 'window.load':1490 'window.location.pathname':857 'within':350 'without':540,587 'woff2':529,1409 'work':1443 'worst':1726 'write':146 'www.competitor-a.com':1185 'www.competitor-b.com':1186 'www.example.com':1018,1066,1157 'www.yoursite.com':1184 'y':1650,1663,1800,1813 'yyyymm':1092,1170,1173","prices":[{"id":"c13f3d8f-5924-4a0e-a0bb-d111254b221d","listingId":"45ec5a38-559a-4d06-9239-e335c4fc7f26","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cognyai","category":"claude-code-marketing-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:23:32.086Z"}],"sources":[{"listingId":"45ec5a38-559a-4d06-9239-e335c4fc7f26","source":"github","sourceId":"cognyai/claude-code-marketing-skills/cwv-audit","sourceUrl":"https://github.com/cognyai/claude-code-marketing-skills/tree/main/skills/cwv-audit","isPrimary":false,"firstSeenAt":"2026-04-18T22:23:32.086Z","lastSeenAt":"2026-05-01T06:56:25.982Z"}],"details":{"listingId":"45ec5a38-559a-4d06-9239-e335c4fc7f26","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cognyai","slug":"cwv-audit","github":{"repo":"cognyai/claude-code-marketing-skills","stars":42,"topics":["agent-skills","ai-agents","claude-code","claude-skills","cluade-mcp","cursor","geo","growth-hacking","llm","marketing","mcp","seo","vibe","windsurf"],"license":null,"html_url":"https://github.com/cognyai/claude-code-marketing-skills","pushed_at":"2026-04-29T13:43:50Z","description":"Marketing skills for Claude Code — SEO audits and implementation, ad analysis, ad optimization. Free skills need no account. $9/mo for live Search Console, Bing & LinkedIn data.","skill_md_sha":"d42bb7f6df92c9df2d776101878fcffb0c65735e","skill_md_path":"skills/cwv-audit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cognyai/claude-code-marketing-skills/tree/main/skills/cwv-audit"},"layout":"multi","source":"github","category":"claude-code-marketing-skills","frontmatter":{"name":"cwv-audit","description":"Core Web Vitals Reference — LCP, INP, CLS thresholds, root causes, optimization fixes, CrUX BigQuery queries, web-vitals library usage, and SEO impact"},"skills_sh_url":"https://skills.sh/cognyai/claude-code-marketing-skills/cwv-audit"},"updatedAt":"2026-05-01T06:56:25.982Z"}}