Full QA Audit — 121 Group (121group.io)
6 blocker · 12 important · 15 recommended · 28 passing · 67 total findings across 10 categories.
Executive summary
This report covers the mandatory 10 audit categories required for every 121 Group pre-launch review. Each finding is classified by severity and assigned a short ID for tracking.
| Severity | Count | Meaning | |---|---|---| | Blocker | 6 | Must be fixed before launch. Real risk to security, accessibility, or basic function. | | Important | 12 | Should be fixed before launch if possible. Noticeable impact on quality. | | Recommended | 15 | Nice to have. Hardening or polish items. | | Already good | 28 | Verified passing. Recorded for transparency. |
Security & hardening
Automated surface-level security audit. Checks version disclosure, exposed files, authentication surface, and security headers. Authenticated checks (wp-config.php hardening, user role audit, plugin CVE matching, debug.log review) require cPanel / wp-admin access — see "Launch readiness" for the follow-up checklist.
Server does not leak PHP/stack version.
https://121group.io/readme.html returns HTTP 200 with full WP version info.
Fix: Block via .htaccess:
<FilesMatch "^(readme|license|CHANGELOG)\.(txt|html|md)$">
Require all denied
</FilesMatch>
Or simply delete the file (it is recreated on core updates — add deletion to post-update runbook).
Although the site is already installed (page shows "Already Installed"), the endpoint itself should be blocked. If the DB is ever corrupted, an attacker who reaches install.php can take over the installation.
Fix: Block via .htaccess:
<Files install.php>
Require all denied
</Files>
All tested sensitive paths return 403 or 404.
Performance & Core Web Vitals
Automated performance audit via Google Lighthouse in mobile-simulated mode (Moto G4, 4G). Score: 46/100. Core Web Vitals measured in lab conditions; real-user metrics may differ. Full Lighthouse report stored in ctx.shared.lighthouse for reference.
Mobile throttled test. Below 50 is Google's "poor" category and actively hurts SEO.
Google considers >4s a poor user experience that will negatively impact SEO ranking.
- Top-rated opportunities:
- Remove unused CSS
- Remove unused JavaScript
Below 0.1 — good.
Users will experience input lag. Audit third-party scripts and JS bundles.
Good.
Heavy page. Target < 2MB. Biggest wins usually come from image optimisation and removing unused JS.
Review plugin output. Lighthouse identified JS that is loaded but not executed on the homepage. Consider conditionally loading scripts only where needed.
Accessibility (WCAG 2.2 AA)
Automated WCAG 2.2 AA audit via axe-core. Homepage tested at 1366×900 viewport. 51 rules passed. Automated tools catch approximately 30-40% of accessibility issues — manual keyboard and screen-reader testing is still required for full compliance.
Across severity levels: 1 critical, 3 serious, 2 moderate, 1 minor.
51 WCAG 2.2 AA rules passed. Note that automated tools catch ~30-40% of accessibility issues; a manual screen-reader pass with NVDA or JAWS is still required before launch for full WCAG compliance.
Rule: aria-allowed-role (minor)
Affects: 33 element(s) on the page
Why it matters: Ensure role attribute has an appropriate value for the element
Example element:
``html
<img decoding="async" src="data:image/png;base6..." alt="" class="uag-image-143 lazylo..." width="985" height="1024" title="" role="img" data-src="https://121group.io/..." data-srcset="https://121grou
``
Selector: a[href$="healthcare/"][target=""][rel="noopener"] >.lazyautosizes
Help: ARIA role should be appropriate for the element (docs)
Rule: aria-prohibited-attr (serious)
Affects: 1 element(s) on the page
Why it matters: Ensure ARIA attributes are not prohibited for an element's role
Example element:
``html
<div class="html5-video-player ytp-hide-controls ytp-exp-bottom-control-flexbox ytp-modern-caption ytp-livebadge-color unstarted-mode ytp-large-width-mode" tabindex="" id="movie_player" data-version="
``
Selector: iframe
Help: Elements must only use permitted ARIA attributes (docs)
Rule: button-name (critical)
Affects: 1 element(s) on the page
Why it matters: Ensure buttons have discernible text
Example element:
``html
<button class="ytmVideoInfoLink ytmVideoInfoChannelAvatar"><img alt="thumbnail-image" class="ytCoreImageHost ytmVideoInfoChannelLogo ytCoreImageFillParentHeight ytCoreImageFillParentWidth ytCoreImageC
``
Selector: iframe
Help: Buttons must have discernible text (docs)
Rule: heading-order (moderate)
Affects: 1 element(s) on the page
Why it matters: Ensure the order of headings is semantically correct
Example element:
``html
<h4 class="uagb-post__title uagb-post__text">
<a href="https://121group.io/marketing-services/branding-brand-strategy/" target="_self" rel="bookmark noopener noreferrer" tabindex="0">Branding & Br
``
Selector: .slick-current > div >.uagb-post__inner-wrap > h4
Help: Heading levels should only increase by one (docs)
Rule: link-name (serious)
Affects: 14 element(s) on the page
Why it matters: Ensure links have discernible text
Example element:
``html
<a class="" href="/healthcare/" target="" rel="noopener">
``
Selector: .swiper-slide-prev >.swiper-content >.uagb-block-115efa57.alignright.wp-block-uagb-image--align-right >.wp-block-uagb-image__figure > a[href$="healthcare/"][target=""][rel="noopener"]
Help: Links must have discernible text (docs)
Rule: region (moderate)
Affects: 7 element(s) on the page
Why it matters: Ensure all page content is contained by landmarks
Example element:
``html
<div class="wp-block-uagb-advanced-heading uagb-block-14917650"><h2 class="uagb-heading-text">Contact Us</h2><p class="uagb-desc-text">Fill out the form below and we will be in touch.</p></div>
``
Selector: .uagb-block-14917650
Help: All page content should be contained by landmarks (docs)
Rule: target-size (serious)
Affects: 12 element(s) on the page
Why it matters: Ensure touch targets have sufficient size and space
Example element:
``html
<a aria-expanded="false" href="https://121group.io/services/" class="menu-link">
``
Selector: #menu-item-413 >.menu-link[href$="services/"]
Help: All touch targets must be 24px large, or leave sufficient space (docs)
SEO
Automated SEO audit: meta tags, canonical, robots, sitemap, Open Graph, Twitter Card, schema.org, mixed content, link inventory. A full SEO audit should also cover keyword research, internal linking depth, and on-page content quality — which are human-judgement tasks beyond this scan.
"Full Service Digital Agency: Brand, Marketing & Digital Services"
https://121group.io/
image: https://121group.io/storage/thumbnail.png
Link validation is performed in the Content Quality category. See there for broken-link findings.
All scripts, styles, images, iframes use HTTPS.
Content quality
Automated content-quality scan of the homepage only. A full content audit should crawl every page. Checks: placeholder text, stale dates, broken links on homepage, NAP consistency, word count, caps-lock usage, plaintext email exposure.
Checked for: Lorem ipsum, TBD, Coming soon, [insert …], etc.
Broken links hurt user trust and SEO. Fix or remove:
https://www.facebook.com/121groupaus/— HTTP 400https://121group.io/our-work/— HTTP 404https://121group.io/case-study/covid-screening/— HTTP 404
UI / UX
Automated UI/UX checks across mobile (390px), tablet (768px), and desktop (1366px) viewports. Screenshots bundled with the published audit. Manual review still needed for: visual hierarchy, brand consistency, CTA wording, form usability flow, and accessibility beyond what axe-core catches.
Homepage tested at 390, 768, 1366 widths.
Saved under published-assets/121group-showcase/. These are bundled with the audit when published.
That's 3% of the 289 interactive elements on the mobile homepage. WCAG 2.2 AA requires a minimum touch target size of 24×24 CSS pixels, but 44×44 is the industry best-practice for thumb accessibility.
Fix: Add minimum padding / min-height to links and buttons in the child theme.
Most jurisdictions expect a Privacy Policy at minimum; Cookie Policy is required under GDPR if analytics are used; Terms of Service is best practice.
Images & media
Scanned 151 <img> element(s) on the homepage. Checked: alt text, explicit dimensions, lazy-loading, responsive srcset, file sizes, Open Graph image, favicon set, logo format.
Every <img> must have an alt attribute. Use an empty alt="" for purely decorative images (screen readers skip them) and descriptive text for meaningful ones.
WordPress adds loading="lazy" automatically via wp_get_attachment_image(). Themes that manually output <img> tags bypass this. Add loading="lazy" to below-the-fold images (and fetchpriority="high" to the LCP image).
Without responsive srcset, every device downloads the same (usually over-sized) image. WordPress emits srcset automatically via wp_get_attachment_image(). Custom template code should use that helper.
https://121group.io/storage/thumbnail.png
Vector, crisp at any resolution, tiny file.
Forms, integrations & conversion
Automated form inspection limited to what's visible in the page HTML. End-to-end form testing (submit → email delivery → CRM sync → thank-you page → analytics event) still requires manual or Cypress/Playwright testing before launch.
- Form #1: action=
https://121group49109.activehosted.com/proc.phpmethod=POST - 13 input(s), 6 label(s)
- Nonce/CSRF token: NO
- Honeypot: not detected
- reCAPTCHA/Turnstile/hCaptcha: detected on page
Fix: WordPress forms must include wp_nonce_field(). Third-party form plugins (Gravity Forms, WPForms, Contact Form 7, Mailchimp for WP) handle this automatically — if one is missing, it usually means a hand-rolled form needs hardening.
Placeholder text is not a replacement for <label>. Every form field should have a visible associated label for accessibility and usability.
Adding autocomplete="email", autocomplete="tel", autocomplete="name" lets browsers pre-fill, improving conversion. Especially important on mobile.
WordPress's native wp_mail() uses the server's mail() function which is notoriously unreliable for deliverability (spam folder, bounces). Install WP Mail SMTP, FluentSMTP, or similar and route through a transactional provider (SendGrid, Postmark, Mailgun, Amazon SES).
- Also verify DNS records:
- SPF TXT record authorising the sender domain
- DKIM for email signing
- DMARC policy for anti-spoofing
Use https://mxtoolbox.com/domain/ to audit.
Analytics, tracking & legal
Surface-level analytics and compliance inspection. Full audit must also verify conversion goals are configured, events fire correctly on key actions (form submit, CTA click, scroll depth), and the cookie consent banner genuinely blocks non-essential trackers before acceptance.
- GTM container:
GTM-MP4TVS2 - GA4:
G-KK58LRW6SX - Hotjar
- Microsoft Clarity
- LinkedIn Insight Tag
Under GDPR (EU), CCPA (California), and increasingly other jurisdictions, analytics/marketing cookies require explicit consent BEFORE they fire. Install Complianz, Cookiebot, or similar and block non-essential trackers until consent is given.
- Legal pages should be linked from every page, typically in the footer. Required minimums:
- Privacy Policy (required in most jurisdictions)
- Terms of Service (protects the business)
- Cookie Policy (required under GDPR if any tracking is present)
Token: wFX9DCUkWGW3oyqFekgt…
Launch readiness & infrastructure
Launch-readiness items combine automated checks with manual verification tasks. The automated items below are flagged; the manual items are included as checklist entries for the team to tick off in-browser.
Cert validation handled by the edge server (Cloudflare or LiteSpeed). Verify the certificate auto-renews and that includeSubDomains HSTS is configured across all production subdomains.
Confirm at least ONE of the following is configured and tested:
- Synergy JetBackup (cPanel → JetBackup 5) — verify last backup ran successfully and restoration has been tested
- UpdraftPlus / BlogVault / ManageWP — scheduled offsite backups
- Host-level snapshots — confirm retention policy
Do a restoration test on staging before launch. An untested backup is not a backup.
Before launch day:
- Lower TTL on production A/CNAME records to 300s (5 min) at least 24 hours before cutover. This allows a fast rollback.
- Document the old DNS configuration (screenshots + export) in case we need to revert.
- Prepare the redirect map (see next item).
- Lock a launch window outside peak traffic hours; inform stakeholders.
- After launch: monitor real-user traffic and errors for 2 hours minimum before raising TTL back to 3600s.
If any URLs have changed between the old and new site (permalink structure, page slugs, category paths), you MUST provide 301 redirects to preserve SEO equity.
- Crawl the OLD production site (e.g. using Screaming Frog) and export the URL list.
- Map every old URL to its new equivalent.
- Implement redirects via Rank Math Redirections, Redirection plugin, or in
.htaccess. - Test 20 random old URLs post-launch and confirm 301 (not 404 or 302).
- A one-page document shared with the team, answering:
- Who authorises a rollback? (RACI)
- How do we restore the previous site? (DNS revert + DB restore)
- How long does it take? (target < 30 mins)
- What communications go out during a rollback?
Post-launch, at minimum:
- Uptime monitor hitting the homepage every 1-5 minutes: UptimeRobot (free), Better Uptime, Pingdom
- Error monitoring for custom PHP/JS: Sentry, Rollbar, or at least enable WP's
WP_DEBUG_LOGin production (carefully) - Analytics real-time view open on launch day
- Search Console coverage report checked daily for first week
cf-ray: 9f756463496ffde7-SIN
Work through within 48 hours of cutover:
- [ ] Submit the XML sitemap to Google Search Console
- [ ] Submit to Bing Webmaster Tools
- [ ] Verify GA4 is receiving data (real-time view)
- [ ] Verify conversion events fire (test each form/CTA)
- [ ] Test 20 random old URLs → confirm 301 to new URL
- [ ] Run PageSpeed Insights on 5 key pages → save baseline
- [ ] Test all forms end-to-end (email delivery, CRM sync)
- [ ] Check 404 page still works
- [ ] Verify backup runs successfully on the new site
- [ ] Stakeholder sign-off captured in writing