Content operations skills for AEM Edge Delivery Services: page auditing, SEO optimization, AI search (GEO), WCAG accessibility, bulk metadata, structured data, sitemap validation, and content diffing. Complements the EDS development skills with operational tooling for content teams.
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Turn Operational Telemetry (OpTel, formerly RUM) data of a site into a short list of pages and causes. This skill reads and interprets the data. cwv-optimizer fixes what it finds. It does not set up data collection.
RUM_DOMAIN_KEY environment variable. Never print it, write it to a file, or put it in a report, a commit or a pull request.domainkey=…). Don't copy such a URL into a report, and tell the user when they paste one.https://bundles.aem.page for the domain the user named.Ask for the domain and the period. For a question about a change ("since the deploy", "this week"), ask for the period before it too. Then take the first of these that the user can give you:
https://tools.aem.live/tools/optel/explorer/explorer.html?domain=<domain>&view=month. Ask which filters were set. Go to Step 3 with what you have, and say in the report that sample counts are unknown.The Explorer writes the key into the address bar while its eye control is open. Closed, the address says domainkey=incognito. Ask the user to close it before they share an address or a screenshot.
scripts/optel-report.mjs is in this skill's directory. It loads the bundles with @adobe/rum-distiller, the library behind the Explorer, so its numbers match what the user sees there.
work=$(mktemp -d) && cp scripts/optel-report.mjs "$work" && cd "$work"
npm install @adobe/rum-distiller@1.24.0
node optel-report.mjs www.example.com --from=2026-10-08 --to=2026-10-14 \
--baseline-from=2026-10-01 --baseline-to=2026-10-07 > report.json--from and --to are UTC dates, both included, at most 92 days. For longer periods name slots instead: 2026/10 is a month, 2026/10/15 a day, 2026/10/15/05 an hour. A year alone returns 404.--baseline-from and --baseline-to add a second period and a change section (Step 4).--device=mobile (or desktop, bot) and --url=<value of "url" in a report> narrow the report. --top=20 lists more pages.failedSlots lists slots that could not be loaded. HTTP 403 means the key is not valid for this domain. Never present totals as covering the period when failedSlots is not empty.What the report holds:
| Field | Content |
|---|---|
site | pageViews with pageViewsMargin, visits, bounceRate, engagementRate, and lcp, cls, inp, ttfb, each with p75, samples, rating (good, ni, poor) and goodShare. lcpInteracted is the LCP of page views with a click. |
devices | The same metrics per device class. |
lcpElements | The selectors that were the LCP element, with page views and LCP. |
checkpoints | Every checkpoint the site sends, with page views. |
topPages | The busiest pages. |
pagesToFix | Pages with a metric that is not good, ranked by page views times severity (3 for poor, 2 for needs improvement). |
pagesSeen, pagesEstimated | Pages in the sample, and an estimate of the pages that had a page view at all. |
These are the mistakes an analysis makes without this skill:
pageViews of the report. Never multiply a count by a fixed 100. The true number is within pageViewsMargin of it, at 95% confidence.lowSample and doesn't rank by it. Widen the period before you quote such a number. Give the sample count with every p75 you report, and never report a mean.site.lcp with site.lcpInteracted. A page view that sits idle can report a paint from long after the load. When the two differ much, report both and trust the second. Leaving out page views that opened in a background tab does not help: those carry almost no LCP value.samples per device before you call CLS good.bounceRate is the share of visits without a click. engagementRate is the share of page views with a click or with more than three blocks or media seen.url values are patterns. Long numbers, hashes, UUIDs and encoded data in a path are replaced with <number>, <hex>, <uuid> and <base64>, so one row can stand for many pages of a template.pagesSeen counts the pages in the sample; pagesEstimated says how many there are. A page that is not in the report is not a page without problems.bot. Leave them out when you quote visitor numbers.lcpElements tells you what to optimize. If one selector with a poor p75 holds most page views, that element is the finding, whatever the page.With a baseline period, the report has baseline and change:
change.lcp, .cls, .inp hold p75, rating and goodShare for both periods, and pValue with significant where both have at least 20 samples. The test is about the p75 itself: aboveCommonP75 is the share of each period's values above the p75 of both periods together, and pValue says whether those two shares differ. It also finds a change that stays within one rating.significant is true, and say by how much with the two p75 values. When it is false, say that the data doesn't show a change. That is not proof that nothing changed. With 100 samples in each period and a typical spread of LCP values, the test finds a p75 that rose by half in about four of five cases, and one that rose by a fifth in about one of five. Under 20 samples there is no test.change.pagesWorse lists the pages whose rating got worse, with a pValue and significant where the page has at least 20 samples in both periods. Start with the significant ones.change.deviceShare and change.lcpElementsNew show a changed device mix or a new LCP element.change.pageViews: traffic changed only if the two numbers are further apart than their margins.Use day slots (--from, --to) for both periods.
For another question (a traffic source, a checkpoint, errors, a conversion, a trend), write a few lines against the library. references/rum-distiller.md has the series, the facets, filters, statistics and the traps of the API. references/optel-context.md says what each checkpoint holds.
Map each failing metric of pagesToFix to its likely cause with "Causes by metric" in references/optel-context.md. Write the report with "Report template" in the same file. Name cwv-optimizer as the next step for each fix.
.tessl-plugin
skills
accessibility-fix
bulk-metadata
content-audit
content-diff
cwv-optimizer
geo-rewrite
heading-optimizer
image-seo
internal-linking
link-rot-scanner
optel-interpreter
performance-budget
product-page-seo
query-index-optimizer
sitemap-audit
structured-data