A continuation of Janady13/crawler-signal-reference / framework-html-meta-refresh.md. The complete source identity, every recorded occurrence, and linked equations are on its first page.
Source transcript · continued
Download complete source text ↓1,878 lines · 58.5 KB
Rejects deployment if any meta refresh found.
### 17.5 The Client Documentation
For each client project:
```
Redirect handling:
Implementation: HTTP 301 via nginx
No meta http-equiv="refresh" used
Per route redirects: see nginx config
Migration cleanup: completed; no legacy meta refresh remains.
Auto refresh:
Not used.
If real time data is needed: JavaScript polling with user pause control.
```
### 17.6 The Federal Subcontract Compliance Note
For SDVOSB federal subcontracting work:
```
WCAG compliance:
Meta refresh check: PASS (none used)
WCAG 2.2.1 Timing Adjustable: compliant
WCAG 3.2.5 Change on Request: compliant
Section 508: aligned
Verification: meta-refresh-audit.sh; Lighthouse audit; manual axe DevTools.
```
---
## 18. AUDIT CHECKLIST
Run through these 30 items.
### Absence verification
1. [ ] No `<meta http-equiv="refresh">` on any indexable URL.
2. [ ] No `<meta http-equiv="refresh">` on any page including landing pages.
3. [ ] No `<meta http-equiv="refresh">` in any template file.
4. [ ] No `<meta http-equiv="refresh">` after migration cleanup.
5. [ ] No `<meta http-equiv="Refresh">` (case variation).
### Redirect implementation
6. [ ] All redirects implemented at HTTP layer (nginx return 301).
7. [ ] HTTP 301 verified via `curl -sI`.
8. [ ] Location header points to correct destination.
9. [ ] Redirects work for HTTPS only (no HTTP fallback).
### 14 paying client subdomain pattern
10. [ ] All 14 paying client subdomain 301s in place.
11. [ ] Each redirects to correct custom domain.
12. [ ] No meta refresh fallback exists.
### WCAG compliance
13. [ ] WCAG 2.2.1 (Timing Adjustable): no time limits set without user control.
14. [ ] WCAG 3.2.5 (Change on Request): no context changes without user request.
15. [ ] Lighthouse meta-refresh audit: passes (score 1).
16. [ ] axe DevTools: no meta refresh violations.
17. [ ] Federal subcontractor sites: zero violations.
### Migration cleanup
18. [ ] Pre migration audit identified all legacy meta refresh.
19. [ ] Each was replaced with HTTP 301 or JavaScript alternative.
20. [ ] Post migration verification confirms removal.
### CMS specific
21. [ ] WordPress: no plugins generating meta refresh.
22. [ ] Drupal: no modules using meta refresh.
23. [ ] Joomla: maintenance mode and registration not using meta refresh.
### Security
24. [ ] No user controlled redirect destinations.
25. [ ] No open redirect vulnerabilities (whitelist if user input involved).
### JavaScript alternatives
26. [ ] If client side redirects needed: WCAG compliant with user controls.
27. [ ] If polling needed: user pause/resume controls present.
28. [ ] No auto refresh without user control.
### Tooling
29. [ ] `meta-refresh-audit.sh` script in `/usr/local/bin/`.
30. [ ] Pre deploy check rejects new meta refresh additions.
A site that passes all 30 has correctly omitted meta refresh in favor of HTTP redirects and JavaScript alternatives.
---
## 19. COMMON PITFALLS
Eleven patterns to recognize and avoid.
**Pitfall 1: Using meta refresh for redirect "because it's easier".**
Symptom: developer adds `<meta http-equiv="refresh" content="0;url=...">` instead of HTTP 301.
Why it breaks: SEO inferior, WCAG violation, security risk.
Fix: HTTP 301 at nginx (or FastAPI for app level).
**Pitfall 2: Auto refreshing dashboards.**
Symptom: dashboard has `<meta http-equiv="refresh" content="30">`.
Why it breaks: WCAG 2.2.1 violation; jarring UX.
Fix: JavaScript polling with user pause control.
**Pitfall 3: Splash page with meta refresh.**
Symptom: 5 second meta refresh transition page.
Why it breaks: WCAG 3.2.5 violation; SEO inferior.
Fix: HTTP 301 (instant) or JavaScript with user control.
**Pitfall 4: WordPress plugin meta refresh.**
Symptom: plugin auto-adds meta refresh for some functionality.
Why it breaks: legacy plugin behavior.
Fix: disable plugin feature; use HTTP redirect alternative.
**Pitfall 5: Meta refresh with user-controlled URL.**
Symptom: `<meta http-equiv="refresh" content="0;url={user_input}">`.
Why it breaks: open redirect vulnerability.
Fix: server side whitelist; never trust user input as redirect destination.
**Pitfall 6: Forgetting meta refresh in template cleanup.**
Symptom: migration mostly done but some old templates still have meta refresh.
Why it breaks: incomplete migration.
Fix: full file system grep; remove all occurrences.
**Pitfall 7: Federal subcontractor site with meta refresh.**
Symptom: WeCoverUSA inherited site with legacy meta refresh.
Why it breaks: Section 508 audit failure.
Fix: immediate cleanup; migration to HTTP 301.
**Pitfall 8: Meta refresh with very short delay (0 or 1 second).**
Symptom: developer thinks "0 second delay is the same as immediate redirect".
Why it breaks: still WCAG violation; SEO inferior; security risk.
Fix: HTTP 301.
**Pitfall 9: Meta refresh with long delay (10+ seconds).**
Symptom: marketing wants "5 second branded transition".
Why it breaks: severe WCAG 2.2.1 violation; user feels trapped.
Fix: JavaScript with user controls.
**Pitfall 10: Meta refresh from PHP redirect function.**
Symptom: legacy PHP code outputs meta refresh tag.
Why it breaks: legacy PHP pattern.
Fix: use PHP `header('Location: ...')` for HTTP redirect.
**Pitfall 11: Meta refresh on 404 page.**
Symptom: 404 page meta refreshes to homepage.
Why it breaks: bad UX; obscures 404 status; WCAG violation.
Fix: proper 404 page with manual links and explanation.
---
## 20. DIAGNOSTIC COMMANDS
Reference of commands useful for meta refresh investigation.
### Inspect a URL
```bash
# Check for meta refresh
curl -s https://example.com/ | grep -c 'meta http-equiv="refresh"'
# Expected: 0
# Get details if present
curl -s https://example.com/ | grep -oE 'meta http-equiv="refresh"[^>]+'
```
### Bulk audit a sitemap
```bash
curl -s https://example.com/sitemap.xml | grep -oE "<loc>[^<]+</loc>" | sed 's/<[^>]*>//g' | while read url; do
HAS=$(curl -s "$url" 2>/dev/null | grep -c 'meta http-equiv="refresh"')
if [ "$HAS" != "0" ]; then
echo "META REFRESH: $url"
fi
done
```
### Find across all client sites
```bash
meta-refresh-audit.sh
```
### Verify HTTP 301 redirect works
```bash
URL=$1
curl -sI "$URL" | head -3
# Expected: HTTP/2 301 with Location header
```
### Verify 14 paying client redirects
```bash
for old in arcounselingandwellness eurekabathworks heritagehardwoodfloors localliving wecoverusa; do
URL="https://${old}.thatwebhostingguy.com"
RESULT=$(curl -sI "$URL" 2>/dev/null | head -3)
echo "$old:"
echo "$RESULT"
echo ""
done
```
### Lighthouse accessibility check
```bash
URL=$1
lighthouse "$URL" \
--only-categories=accessibility \
--quiet \
--output=json \
--output-path=/tmp/lh-a11y.json
python3 -c "
import json
with open('/tmp/lh-a11y.json') as f:
data = json.load(f)
audit = data['audits'].get('meta-refresh', {})
print(f'meta-refresh: {audit.get(\"score\")} - {audit.get(\"title\")}')
"
```
### Browser DevTools verification
In Chrome DevTools:
1. Open the page.
2. Network tab: clear; reload.
3. Look for meta refresh redirect (loads page, then redirects).
4. Compare with HTTP 301 (immediate redirect, no HTML loaded for old URL).
### Apply changes
```bash
# Remove meta refresh from files
find /var/www/sites/ -name "*.html" -type f -exec \
sed -i '/meta http-equiv="refresh"/d' {} \;
# Apply nginx changes if 301 redirects added
nginx -t && systemctl reload nginx
```
---
## 21. CROSS-REFERENCES
* [framework-http-3xx-status-codes.md](framework-http-3xx-status-codes.md): the canonical HTTP redirect mechanism (301, 302, 307, 308). Section 16 documents Joseph's 14 paying client subdomain 301 pattern.
* [framework-html-meta-content-language.md](framework-html-meta-content-language.md): also discourages legacy http-equiv mechanisms; both prefer proper HTTP-layer or modern HTML alternatives.
* [framework-html-meta-robots.md](framework-html-meta-robots.md): redirects and noindex interaction.
* [framework-html-meta-charset.md](framework-html-meta-charset.md): meta tag placement order in head.
* [framework-http-security-headers.md](framework-http-security-headers.md): security header coordination including Referrer-Policy on redirects.
* [framework-http-performance-headers.md](framework-http-performance-headers.md): performance considerations for redirects.
* [UNIVERSAL-RANKING-FRAMEWORK.md](UNIVERSAL-RANKING-FRAMEWORK.md): redirect handling part of ranking; HTTP 301 is the canonical signal.
* [SEO-BUILD-REFERENCE.md](SEO-BUILD-REFERENCE.md) v2.4: the build playbook including redirect implementation.
* W3C HTML meta refresh: https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
* W3C WCAG 2.2.1 Timing Adjustable: https://www.w3.org/WAI/WCAG21/Understanding/timing-adjustable.html
* W3C WCAG 3.2.5 Change on Request: https://www.w3.org/WAI/WCAG21/Understanding/change-on-request.html
* MDN meta http-equiv="refresh": https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
* Google Search Central on redirects: https://developers.google.com/search/docs/crawling-indexing/301-redirects
* OWASP Unvalidated Redirects: https://owasp.org/www-community/attacks/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
* Section 508 Standards: https://www.access-board.gov/ict/
---
## APPENDIX A: ONE PAGE QUICK REFERENCE
For the person who just wants the answer.
### The Bubbles rule
**Never use `<meta http-equiv="refresh">`. Use HTTP 301 for redirects. Use JavaScript with user controls for auto refresh.**
### The canonical replacements
```nginx
# Redirect via HTTP 301 (preferred)
location /old-path/ {
return 301 /new-path/;
}
```
```javascript
// Auto refresh via JavaScript with user control
let pollInterval;
const startPolling = () => {
pollInterval = setInterval(updateData, 30000);
};
document.getElementById('pause').addEventListener('click', () => {
clearInterval(pollInterval);
});
```
### The forbidden patterns
```html
<!-- NEVER USE -->
<meta http-equiv="refresh" content="0;url=https://new-url.com/">
<meta http-equiv="refresh" content="5;url=https://new-url.com/">
<meta http-equiv="refresh" content="30">
<meta http-equiv="refresh" content="60">
```
### Why
* SEO: HTTP 301 transfers ~95% PageRank; meta refresh ~70-85%.
* Accessibility: WCAG 2.2.1 and 3.2.5 violations.
* Performance: meta refresh requires full HTML download.
* Security: open redirect risk.
* Federal subcontracting: Section 508 audit failures.
### Five rules to memorize
1. **For redirects: HTTP 301 at nginx (or FastAPI 301).**
2. **For auto refresh: JavaScript with user pause/resume controls.**
3. **Migration cleanup: remove ALL meta refresh tags.**
4. **Federal subcontracting: zero tolerance.**
5. **The 14 paying client pattern uses HTTP 301 only.**
### Five commands every operator should know
```bash
# 1. Check for meta refresh (should be 0)
curl -s URL | grep -c 'meta http-equiv="refresh"'
# 2. Audit all sites
meta-refresh-audit.sh
# 3. Verify a 301 redirect works
curl -sI URL | head -3
# 4. Remove meta refresh from files
find /var/www/sites/example.com/ -name "*.html" -type f -exec sed -i '/meta http-equiv="refresh"/d' {} \;
# 5. Apply nginx changes
nginx -t && systemctl reload nginx
```
### Three end to end tests
```bash
# 1. No meta refresh anywhere
URL=https://example.com/
HAS=$(curl -s "$URL" | grep -c 'meta http-equiv="refresh"')
[ "$HAS" = "0" ] && echo "OK" || echo "FAIL: $HAS occurrences"
# 2. Redirects use HTTP 301
OLD_URL=https://old.example.com/
STATUS=$(curl -sI "$OLD_URL" 2>/dev/null | head -1 | awk '{print $2}')
[ "$STATUS" = "301" ] && echo "OK: HTTP 301" || echo "FAIL: $STATUS"
# 3. WCAG compliance
lighthouse URL --only-audits=meta-refresh --quiet --output=json --output-path=/tmp/lh.json
SCORE=$(python3 -c "import json; print(json.load(open('/tmp/lh.json'))['audits']['meta-refresh']['score'])")
[ "$SCORE" = "1" ] && echo "OK: WCAG passes" || echo "FAIL: WCAG violation"
```
If all three pass AND `meta-refresh-audit.sh` shows zero across all sites AND Lighthouse accessibility score is 100, the meta refresh layer is correctly handled (which is to say: absent).
---
End of framework-html-meta-refresh.md.