plugins/aem/edge-delivery-services-content-ops/skills/bulk-metadata/SKILL.md
Audit and update metadata across multiple AEM Edge Delivery Services pages. Scans pages via the query index, identifies missing or inconsistent metadata (titles, descriptions, og tags, robots), and generates a corrected bulk metadata spreadsheet. Use when standardizing metadata across a site, preparing for launch, or fixing SEO issues at scale.
npx skillsauth add adobe/skills bulk-metadataInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Audit metadata across an entire AEM Edge Delivery Services site using the query index, identify gaps and inconsistencies, and produce a corrected bulk metadata spreadsheet ready to paste into Google Sheets or Excel.
This skill fetches external web pages and JSON endpoints for analysis. When fetching:
EDS metadata is managed at three levels, with a clear precedence order:
<meta> tags in the page <head>. Page-level always wins.metadata.xlsx (or metadata Google Sheet) placed in a subdirectory. Applies to all pages in that folder and below.metadata.xlsx (or metadata Google Sheet) in the site root. Uses URL pattern matching to set defaults across the entire site.Precedence: page > folder > bulk. Bulk metadata sets defaults; page-level metadata always overrides.
The bulk metadata spreadsheet uses URL patterns in the first column:
/** — matches all pages site-wide (deepest wildcard)/blog/** — matches all pages under /blog/ at any depth/blog/* — matches only direct children of /blog/ (one level)/about — matches a single specific pageThe spreadsheet is evaluated top-to-bottom. Put broad patterns first, specific overrides later.
noindex robots directives to draft or staging content.Before starting, create a checklist of all steps to track progress:
Fetch the site's query index to get a listing of all indexed pages:
https://<branch>--<repo>--<owner>.aem.live/query-index.json?limit=1000
If the user provides a production URL instead, derive the AEM URL or ask for the owner, repo, and branch values.
The query index returns an object with a data array. Each entry contains:
path — the page path (e.g., /blog/my-post)title — the page title from metadatadescription — the page description from metadataimage — the page's OG image pathlastModified — Unix timestamp of last modificationThere may also be custom properties defined in the site's helix-query.yaml configuration.
If the index returns exactly the limit number of results, warn the user that there may be more pages. Suggest increasing the limit or paginating with the offset parameter.
If the query index returns a 404 (no helix-query.yaml configured), use this fallback chain:
https://<branch>--<repo>--<owner>.aem.live/sitemap.xml. Parse <url><loc> entries to build a page list.For each page returned by the query index, check:
/ or be a full URL.robots meta tag. Most published pages should not have noindex — flag any production page with noindex as a critical issue./drafts/ or test paths should have noindex if they appear in the query index.For a deeper audit, optionally fetch individual pages' HTML to check their full <meta> tags (og:title, og:description, robots, canonical). Only do this if the user requests a deep audit or the site has fewer than 50 pages.
If a bulk metadata spreadsheet already exists, fetch it:
https://<branch>--<repo>--<owner>.aem.live/metadata.json
This returns the spreadsheet as JSON with a data array. Each entry has properties matching the spreadsheet column headers (URL, Title, Description, Image, etc.).
If this returns a 404, there is no bulk metadata spreadsheet yet — note this and proceed.
If it exists, analyze the current rules:
Present a summary table of all pages with their metadata status:
| # | Path | Title | Title Len | Title OK? | Description | Desc Len | Desc OK? | Image | Issues | |---|------|-------|-----------|-----------|-------------|----------|----------|-------|--------| | 1 | /about | About Us | 8 | Short | Our company... | 142 | OK | /media/hero.jpg | Title too short | | 2 | /blog/post-1 | | — | Missing | | — | Missing | | No title, no description, no image |
Produce a metadata spreadsheet table that the user can paste directly into a Google Sheet or Excel file. This is the corrected/improved version of the bulk metadata.
Format:
| URL | Title | Description | Image | Robots | Template | |-----|-------|-------------|-------|--------|----------| | /** | [site default title suffix] | [site default description] | [default og:image path] | | | | /blog/** | | | /media/blog-default.jpg | | article | | /drafts/** | | | | noindex | | | /events/* | | | /media/events-hero.jpg | | event |
/**) go first. These set the baseline defaults."" (empty string) to explicitly clear a value inherited from a broader pattern if needed.Robots value, omit that column.* (single path level) and ** (deep path).Based on the audit findings:
/blog/**, /products/**) and set section-level defaults.noindex rules for draft, staging, or test content paths.Tell the user exactly how to implement the bulk metadata spreadsheet:
nav and footer documents), create a new Google Sheet named metadata.After publishing, verify the metadata is applied:
https://<branch>--<repo>--<owner>.aem.live/metadata.json and confirm your rules appear.<meta> tags in the page source.| Problem | Cause | Solution |
|---------|-------|----------|
| Query index returns empty or 404 | Site may not have a query index configured, or the URL is wrong | Verify the owner, repo, and branch values; check that helix-query.yaml exists in the repo |
| Metadata changes not appearing on pages | Page-level metadata is overriding bulk metadata | This is expected behavior — page-level always wins |
| Metadata.json returns 404 | No bulk metadata spreadsheet exists yet | This is fine — the user will create one using the generated spreadsheet |
| Patterns not matching expected pages | Pattern syntax may be wrong | Use /** for deep paths, /* for single-level; patterns must start with / |
| Spreadsheet changes not taking effect | Spreadsheet may not be published | Open Sidekick on the spreadsheet and click Publish |
| Too many pages in the index | Query index has a default limit | Use ?limit=1000 or paginate with ?offset=1000&limit=1000 |
tools
Identifies which items (pages, campaigns, products, channels, regions) had the biggest increases or decreases for a key metric between two time periods. Use this skill when someone asks "what's up and what's down," "which campaigns moved the most," "top gainers and losers," "what pages are trending," "show me what changed by channel," or any variation of identifying the biggest movers and decliners for a metric.
tools
Compares the performance of two or more audience segments across key metrics side by side. Use this skill when someone wants to compare audiences, cohorts, or groups — for example, "how do mobile users compare to desktop users on conversion," "compare new vs. returning visitors," "show me the difference between these two segments," "compare these audiences on our KPIs," or "which segment performs better." Also trigger for "segment comparison," "audience comparison," or "cohort comparison."
business
Produces a compact KPI digest showing how key metrics changed over a period and what's driving the movement. Use this skill when someone asks for a performance summary, a weekly recap, a morning briefing, a KPI update, or any variation of "how did we do this week/month." Also trigger for requests like "give me a performance overview," "what moved in the last 7 days," "pull our KPI report," or "summarize our metrics."
testing
Analyzes a multi-step conversion funnel to find where users drop off and which steps have the worst leakage. Use this skill when someone describes a journey or funnel and asks about conversion rates, drop-off, fallout, or step completion. Trigger for phrases like "analyze our onboarding funnel," "where are users dropping off," "what's our checkout conversion rate," "funnel analysis," "show me fallout between these steps," or "which step loses the most users."