| name | email-qa-review |
| platforms | ["cowork","claude-code"] |
| description | Run a structured 18-check QA review on a marketing or lifecycle email proof before it ships. Use this skill when the user asks to QA an email, review an email proof, check an email before sending, audit email quality, or validate a HubSpot proof. Also trigger on 'review this proof', 'is this email ready to send', 'check the email links', 'email QA', or when someone shares a proof email and asks for a pre-send review. Browser-assisted: follows every link to its destination, calculates real WCAG contrast, and screenshots mobile renders. For writing email copy, use brand-voice-writer; for nurture-sequence planning, use email-nurture-planner. |
| references | ["product-marketing-context","brand-voice-guide","brand-guidelines"] |
Email QA Review
Perform a comprehensive pre-send quality review on a marketing or lifecycle email proof. The skill spans 18 checks across content, brand, legal, and technical requirements, and produces a markdown report with a PASS / WARN / BLOCK verdict and a pre-deployment sign-off checklist.
This skill reviews an email — it does not write copy (use brand-voice-writer) or plan sequences (use email-nurture-planner). It also does not post results to Asana or Slack; it produces a report the user acts on.
When to use this skill
- Someone asks to QA, review, or audit an email proof before it sends
- Someone pastes or points at a HubSpot proof email and asks "is this ready to send?"
- Someone asks to check email links, contrast, mobile rendering, or legal compliance
- After
brand-voice-writer produces email copy, as the pre-send quality gate
Step 0: Pre-flight check
Invoke the marketing-preflight skill via the Skill tool, passing this skill's name: field value (email-qa-review) as the args. Do not proceed until it completes successfully. If it stops with an error, follow its instructions and stop.
If marketing-preflight returned a stale-connector footer note, append it verbatim at the end of your final response to the user.
Once pre-flight is complete, fetch this skill's reference docs. Fetch them one at a time, not all in one call — the combined payload (~78K chars) overflows the tool's token limit and spills to a file:
get_marketing_reference(slug: "brand-voice-guide") # style, capitalization, emoji, restricted-language, naming rules — fetch first
get_marketing_reference(slug: "product-marketing-context") # value prop + proof points — for Checks #8–10
get_marketing_reference(slug: "brand-guidelines") # visual/logo/color standards — for Check #11 only
brand-voice-guide covers the content/style checks (#7–#9) and is the one you always need. Pull product-marketing-context for messaging/vertical checks and brand-guidelines for the visual check only when you reach them. Do not hardcode brand rules — always grade against the fetched docs.
If a fetch still overflows to a saved file: read the saved file in chunks (or grep it for the specific rule — naming, capitalization, restricted words). Do not skip the brand checks because the doc was large.
Step 1: Gather inputs
Before reviewing, confirm two things with the user:
- The production subject line — the subject that will actually ship to subscribers. This is the source of truth for Check #1. See the HubSpot note below for why this matters.
- Where the proof is — a Gmail message the user can point you to, a pasted HTML/text body, or a forwarded email. The default path is a HubSpot proof sitting in a review inbox in Gmail.
If the user hasn't given the production subject line, ask for it. If they can't, fall back to the prefix-stripped scraped subject (Step 2).
HubSpot proof caveat — read before grading the subject. HubSpot prepends a test prefix (e.g. [TEST], Test:) to the subject of preview/test sends. The prefixed string is not what subscribers see. Use the rendered Gmail subject only to locate the email — grade the production subject line in Check #1, never the [TEST]-prefixed one. If no production subject was provided, strip a leading test prefix with ^\[?\s*TEST\s*\]?:?\s* (case-insensitive) and grade the remainder, and flag in the report that the subject was inferred.
Step 2: Locate and extract the email
If the user pasted the email body or shared a file, use that directly and skip to link extraction.
Otherwise, use Claude in Chrome (load the browser tools via ToolSearch first):
- Navigate to
https://mail.google.com. Switch to the review-inbox account if needed.
- Search by the production subject line (token search tolerates the
[TEST] prefix and will still surface the proof). Open the most recent matching message.
- Extract the rendered body:
document.querySelector('.a3s').innerText
- Extract links:
Array.from(document.querySelector('.a3s').querySelectorAll('a')).map(a => ({ text: a.innerText.trim(), href: a.getAttribute('href') }))
- Extract images:
Array.from(document.querySelector('.a3s').querySelectorAll('img')).map(img => ({ alt: img.getAttribute('alt'), width: img.getAttribute('width') }))
- Extract preheader text from hidden spans (
display:none / opacity:0 near the top of the HTML).
- Extract inline CSS
background-color and color values for the contrast math in Check #16.
If the proof can't be found, stop and report: "Proof email not found. Subject searched: {subject}. Please verify the production subject line or share the email directly."
Step 3: Test ALL links — destination AND semantic validation
Heads up before you start: following links navigates the browser, so each one may prompt the user for approval, and it registers a hit on your real landing pages / HubSpot tracking URLs. Tell the user this up front. If they decline live navigation, degrade gracefully: validate links structurally instead (wrapper domain, anchor-text ↔ intent match, unsubscribe present) and mark destinations as "not verified — live navigation declined" rather than skipping the check.
For every link except unsubscribe:
3a. Follow each link to its final destination and record the final URL. HubSpot wraps tracked links through its click/tracking domain (e.g. *.hubspotlinks.com or your tracking subdomain) — follow the redirect chain to the true landing page; don't grade the wrapper.
3b. Semantic validation — verify the destination fits the email topic and link text:
- "Start free trial" / "Get started" → signup or pricing ✅
- "Book a demo" → demo booking page ✅
- "Learn more about [feature]" → a relevant docs/help article ✅
- Logo link → homepage or app dashboard ✅
- Social icons → the correct brand social profile ✅
- "here" / vague text → flag the destination AND the non-descriptive text (Check #16)
Severity:
- CRITICAL: Primary CTA resolves to 404, error, or completely wrong destination
- HIGH: Secondary link resolves to wrong/irrelevant destination
- MEDIUM: Reaches the right general area but not the most specific page
3c. Unsubscribe — ⚠️ DO NOT CLICK. In a HubSpot proof, clicking unsubscribe can opt the review inbox out. Identify the unsubscribe link by pattern (HubSpot uses hs-manage-email / hs/manage-preferences / an unsubscribe path) and visual-check only: present, readable, labeled "Unsubscribe."
3d. Document results:
| Link Text | Expected Destination | Actual Final URL | Semantic Match | Status |
|---|
Step 4: Run the 18-check QA
Use the link table from Step 3 for Check #4 — do not re-test links. Grade every brand check against the docs fetched in Step 0.
Status thresholds
- PASS ✅: 0 Critical, 0 High
- WARN ⚠️: 0 Critical, 1+ High
- BLOCK ❌: 1+ Critical
Critical pre-send checks
1. Subject line — grade the production subject (see Step 1 HubSpot note), not the scraped [TEST] version.
- Clarity: immediately understandable
- Length: ≤50 characters (measured on the production subject)
- Spam triggers: no excessive special characters or ALL CAPS
- Complements the preheader without repeating it
- Clear value proposition / hook
2. Preview text / preheader
- Present (not defaulting to "View in browser")
- 85–100 characters optimal
- Extends the subject, doesn't repeat it
- No stray HTML artifacts
3. Call to action
- Primary CTA above the fold (desktop + mobile)
- Minimum 44×44px touch target
- One primary CTA only
- Action-oriented verbs; casing per
brand-voice-guide
4. Link validation — use the Step 3 table. Confirm every CTA resolves correctly and semantically.
5. Personalization tokens — HubSpot-specific. HubSpot syntax is {{ contact.firstname }} / {% ... %}. In a rendered proof, tokens usually display resolved sample/default values, not raw tokens — so a proof can't fully prove fallbacks or conditional logic. Check what's observable (no broken/empty token output, no literal {{ }} leaking through, sample values look sane) and explicitly note in the report that fallback and conditional-logic verification requires a HubSpot preview-as-contact test, not a proof.
6. Legal compliance (CAN-SPAM)
- Physical company address in the footer
- Unsubscribe link present, easy to find, one-click (visual check only — see Step 3c)
- Clear "From" name — HubSpot caveat: a preview/test send shows HubSpot's sender (e.g.
Marketing Email Preview Send <noreply@hubspot.com>), not the production From name. You can't grade this from a proof — flag it in the report as requiring confirmation against the live send's sending profile.
- Subject accurately reflects content
Content quality checks
7. Copyediting & style — grammar, typos, logical flow, no repeated paragraphs. Apply the capitalization, em-dash, exclamation, emoji, and restricted-language rules from brand-voice-guide. Pricing language must match the current pricing page exactly — flag any discrepancy.
8. Brand messaging alignment — message ladders to the core value prop and connects to a proof point from product-marketing-context.
9. Brand voice & persona — copy embodies the tonal pillars in brand-voice-guide without crossing into off-brand territory.
10. Vertical-specific language (if applicable) — correct professional terminology for the target vertical; avoid generic language when targeting a specific one.
11. Visual brand consistency — logo is the correct version/size with alt text; only approved colors per brand-guidelines; product screenshots show current UI.
Technical checks
12. Spam flag analysis — excessive $$$, hype words (FREE, ACT NOW, LIMITED TIME), >80% image-heavy, ALL CAPS, too many exclamation points. Score: Low (0–2 minor) · Medium (3–5 minor or 1 major) · High (6+ or multiple major).
13. HTML review — email-safe HTML (no JS/iframes), critical CSS inline, responsive (max-width + 100% widths), total size <1MB (ideally <600KB; Gmail clips at ~102KB).
14. Image optimization & alt text — each image <200KB, total <1MB; every image has descriptive alt conveying meaning ("Save $8,000 annually", not "graph"); decorative images use alt="".
15. Plain-text version — exists and is readable (not stripped HTML); URLs spelled out; CTA clear; all critical content present.
16. Accessibility (A11y) — calculate the actual WCAG contrast ratio, do NOT just flag "verify":
- Extract hex
background-color and color from inline CSS
- Normalize each channel to 0–1, then linearize: if
c ≤ 0.03928 → c/12.92, else → ((c+0.055)/1.055)^2.4
- Relative luminance:
L = 0.2126·R + 0.7152·G + 0.0722·B
- Ratio:
(L_lighter + 0.05) / (L_darker + 0.05)
- Thresholds: normal body text 4.5:1, large text (18pt+ or 14pt+ bold) 3:1 for WCAG AA
- Fails AA → HIGH; borderline (within 10% of threshold) → MEDIUM with the exact ratio; passes → note the value
Also: descriptive link text (not "click here"/"read more"/"here"), proper heading hierarchy, minimum 14px body text.
17. Mobile optimization — resize_window resizes the user's live browser window, which is disruptive — ask before doing it, and skip it if they'd rather not. When approved, using Claude in Chrome: resize_window to 375×812 (iPhone SE) → screenshot, then 390×844 (iPhone 14) → screenshot, then restore to 1440px. If skipped, flag mobile as needing a seed-list/device test. Verify single-column layout, ≥14px body / ≥22px headlines, ≥44×44px tap targets, images resize without horizontal scroll, critical content above the fold, no horizontal scrolling. (Gmail app, Apple Mail, and Outlook desktop still need seed-list/device testing.)
Analytics & strategy
18. Segmentation & targeting — segment defined, exclusions identified (recently contacted, already converted, unengaged), content appropriate for the segment tier, not promoting features the segment already has.
Output format
Produce a markdown report. In Claude Code, offer to save it to a file the user names; in Cowork, render it inline. Do not write to Asana, Slack, or any metrics log — this skill produces the report only.
EMAIL QA REPORT
Campaign: {name / production subject}
Reviewed: {date}
Reviewer: Claude Email QA
OVERALL STATUS: {✅ PASS | ⚠️ WARN | ❌ BLOCK}
{C} Critical · {H} High · {M} Medium · {L} Low
For each finding:
{❌ CRITICAL | 🔴 HIGH | 🟡 MEDIUM | 🔵 LOW} — {Check name}
Location: {where in the email}
Current: {what it says now}
Should be: {the fix}
Reference: {brand doc or rule}
End with the sign-off checklist:
[ ] All CRITICAL issues resolved
[ ] All HIGH issues resolved
[ ] All CTA links tested and verified
[ ] Unsubscribe link visually present (NOT clicked)
[ ] Production subject line graded (not the [TEST] proof subject)
[ ] Production From name confirmed against the live sending profile (proof shows HubSpot's preview sender)
[ ] Token fallbacks verified via HubSpot preview-as-contact (not just the proof)
[ ] Mobile verified at 375px + 390px
[ ] Seed list tested on target email clients
[ ] Legal compliance confirmed (address, unsubscribe, accurate subject)
[ ] Brand standards met
[ ] Approved by: _______________
[ ] Ready to send: YES / NO
Dependencies
- Required: Tiger Den connector (brand reference docs).
- Optional but recommended: Claude in Chrome — needed for live link-following, real WCAG contrast extraction, and mobile-render screenshots. Without it, Checks #4, #16, and #17 degrade to advisory ("verify manually") and the skill grades only the email content the user pastes in.