aa-conversion-funnel-a…
Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have…
Authenticate with AEM Edge Delivery Services. Opens browser for login and captures token. Works for admin.hlx.page and Config Service APIs regardless of content source (Document Authoring, SharePoint, or Google Drive).
$ npx -y skills add adobe/skills --skill auth --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/authContext preview
The summary Claude sees to decide when to auto-load this skill.
Authenticate with AEM Edge Delivery Services. Opens browser for login and captures token. Works for admin.hlx.page and Config Service APIs regardless of content source (Document Authoring, SharePoint, or Google Drive).
name: auth description: Authenticate with AEM Edge Delivery Services. Opens browser for login and captures token. Works for admin.hlx.page and Config Service APIs regardless of content source (Document Authoring, SharePoint, or Google Drive). license: Apache-2.0 allowed-tools: Read, Write, Edit, Bash, AskUserQuestion metadata: version: "2.0.0"
Authenticate to obtain a token for all Edge Delivery Services admin operations. Auto-detects identity provider from org+site — no content source question needed. Opens the user's default browser for login and receives the token via a local callback server.
The `authToken` works for admin APIs:
| API | Header | Usage | |-----|--------|-------| | `admin.hlx.page` | `x-auth-token: ${AUTH_TOKEN}` | Preview, publish, status, code sync, jobs, logs, config | | Config Service | `x-auth-token: ${AUTH_TOKEN}` | Sites, config, secrets, API keys, profiles |
> **Note:** `admin.da.live` uses a separate Adobe IMS token with `Authorization: Bearer` header. See the DA-specific login flow in `ops/resources/da.md`.
---
Tokens are cached at the **user level** (`~/.aem/ims-token.json`), shared across all projects.
mkdir -p "${HOME}/.aem"
AUTH_TOKEN=$(node -e "
const fs = require('fs');
try {
const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));
if (t.authToken && t.authTokenExpiry > Math.floor(Date.now()/1000) + 60) {
process.stdout.write(t.authToken);
}
} catch (e) {}
")
if [ -n "$AUTH_TOKEN" ]; then
echo "Token valid"
exit 0
fi
echo "Token missing or expired. Starting login..."The auto-login endpoint `/login/{org}/{site}/main` redirects to the correct identity provider automatically — no need to know the content source.
**Resolve org and site from available sources (project-config, ops-config, git remote):**
# Try project-config first (handover context)
ORG=$(cat .claude-plugin/project-config.json 2>/dev/null | node -e "
const d = require('fs').readFileSync(0,'utf8');
try { process.stdout.write(JSON.parse(d).org || ''); } catch(e) {}
")
# Fallback to ops-config (ops context)
if [ -z "$ORG" ]; then
ORG=$(node -e "
const fs = require('fs');
try {
const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));
process.stdout.write(c.org || '');
} catch(e) {}
")
fi
# Site: try git remote first, then ops-config
SITE=$(basename -s .git $(git remote get-url origin 2>/dev/null) 2>/dev/null)
if [ -z "$SITE" ]; then
SITE=$(node -e "
const fs = require('fs');
try {
const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));
process.stdout.write(c.site || '');
} catch(e) {}
")
fi
echo "org=${ORG:-NOT SET} site=${SITE:-NOT SET}"**If `ORG` is empty**, ask the user:
> "I need your organization name to authenticate. You can provide either: > - The org name (the `{org}` in `https://main--site--{org}.aem.page`) > - A preview/live URL like `https://main--mysite--myorg.aem.page/`"
**If user provides a URL**, parse org and site from it:
URL="$USER_INPUT"
if echo "$URL" | grep -q '\.aem\.page\|\.aem\.live'; then
HOST_PART=$(echo "$URL" | cut -d'/' -f3 | cut -d'.' -f1)
ORG=$(echo "$HOST_PART" | awk -F'--' '{print $NF}')
SITE=$(echo "$HOST_PART" | awk -F'--' '{print $(NF-1)}')
echo "Parsed from URL: org=$ORG site=$SITE"
fi**If `SITE` is still empty** (not in a git repo and no URL provided), ask the user:
> "I also need a site name to auto-detect your login provider. What is your site name? (the `{site}` part of `https://main--{site}--{org}.aem.page`)"
**Do NOT proceed until both org and site are available.**
Opens the user's default browser for login. A temporary local HTTP server receives the token callback after login completes. The user must click "Send" on the confirmation page to deliver the token. Works with all identity providers (Adobe IMS, Google, Microsoft).
**User-facing message (display BEFORE running the script below):**
> **Browser opened for login to `{org}/{site}`. Click "Send" after authenticating — you can close the tab once done.**
Use bold/highlighted formatting so the instruction stands out clearly.
mkdir -p "${HOME}/.aem"
node -e "
const http = require('http');
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const TOKEN_PATH = path.join(process.env.HOME, '.aem', 'ims-token.json');
const ORG = '${ORG}';
const SITE = '${SITE}';
const STATE = crypto.randomUUID();
const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
res.writeHead(204);
res.end();
return;
}
if (req.method === 'POST') {
let body = '';
req.on('data', (chunk) => { body += chunk; });
req.on('end', () => {
try {
const parsed = JSON.parse(body);
if (parsed.state !== STATE) {
console.error('State mismatch — ignoring callback');
res.writeHead(403);
res.end('State mismatch');
return;
}
const authToken = parsed.authToken;
if (authToken) {
const expiresAt = Math.floor(Date.now() / 1000) + 86400;
fs.writeFileSync(TOKEN_PATH, JSON.stringify({
authToken,Repo: adobe/skills
Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have…
Generates a concise, executive-ready performance summary covering key metrics, trends, and…
Produces a compact KPI digest showing how key metrics changed over a period and what's…
Compares the performance of two or more audience segments across key metrics side by side.…
Identifies which items (pages, campaigns, products, channels, regions) had the biggest…
Comprehensive dimension analysis and reporting for CJA. Use this skill whenever the user…