Audit

20260715T071520Z-8820

← Back to playee
Audited URL
https://play.ee/
Timestamp
2026-07-15T07:22:47.251Z
Kind
site
Pages
7
Audit summary
https://play.ee/
7 of 7 pages audited
Pagespeed scores
Other checks
LLM Report

Weighted audit summary

75
Overall site quality
Needs Improvementhigh confidence

Site overall 75 is the mean of 7 pages. Scores range 72 (https://play.ee/web-development-in-estonia/) → 78 (https://play.ee/wordpress-support-service/). Weakest page: PSI mobile 93 (desktop 100) shows strong performance, but LCP 2.6 s and FCP 1.99 s are in warning zones. Security headers score 20/100 is a major drag — HTTP does not redirect to HTTPS, HSTS missing, CSP weak. Accessibility has 1 serious color-contrast violation affecting 21+ nodes plus missing main landmark. W3C validator reports 7 errors with parser recovery failure at line 100. Image dimensions missing on 69 images is a CLS risk despite current 0.000 CLS score.

Per-page scores
78
Home
high
76
…evelopment-case-studies
high
74
…-development-work-index
high
78
…rdpress-support-service
high
72
…-development-in-estonia
high
77
…-development-in-estonia
high
72
…ite-development-contact
high

Audit Report: Perfectly formed web development team - gotoAndPlay

Website: https://play.ee/
Date: 2026-07-15

Overall Score: 75 / 100
Status: 🟡 Needs Improvement
Confidence: high
Audit Coverage: 100% — all sources returned data

Pages Audited (7 of 7):

Summary

Site overall 75 is the mean of 7 pages. Scores range 72 (https://play.ee/web-development-in-estonia/) → 78 (https://play.ee/wordpress-support-service/). Weakest page: PSI mobile 93 (desktop 100) shows strong performance, but LCP 2.6 s and FCP 1.99 s are in warning zones. Security headers score 20/100 is a major drag — HTTP does not redirect to HTTPS, HSTS missing, CSP weak. Accessibility has 1 serious color-contrast violation affecting 21+ nodes plus missing main landmark. W3C validator reports 7 errors with parser recovery failure at line 100. Image dimensions missing on 69 images is a CLS risk despite current 0.000 CLS score.

Per-Page Scores

Page Score Status Confidence
https://play.ee/ 78 🟡 Needs Improvement high
https://play.ee/web-development-case-studies/ 76 🟡 Needs Improvement high
https://play.ee/software-development-work-index/ 74 🟡 Needs Improvement high
https://play.ee/wordpress-support-service/ 78 🟡 Needs Improvement high
https://play.ee/web-development-in-estonia/ 72 🟡 Needs Improvement high
https://play.ee/software-development-in-estonia/ 77 🟡 Needs Improvement high
https://play.ee/website-development-contact/ 72 🟡 Needs Improvement high

PageSpeed Insights — Mobile vs Desktop

Lower is worse for Performance; higher is worse for LCP and CLS. Worse value is bolded.

URL Performance (M / D) LCP (M / D) CLS (M / D)
https://play.ee/ 95 / 100 2.51 s / 608 ms 0.002 / 0.008
https://play.ee/web-development-case-studies/ 97 / 100 2.10 s / 575 ms 0.003 / 0.003
https://play.ee/software-development-work-index/ 96 / 100 2.33 s / 557 ms 0.041 / 0.003
https://play.ee/wordpress-support-service/ 97 / 100 2.33 s / 546 ms 0.017 / 0.003
https://play.ee/web-development-in-estonia/ 93 / 100 2.64 s / 532 ms 0.000 / 0.005
https://play.ee/software-development-in-estonia/ 96 / 100 2.48 s / 574 ms 0.003 / 0.004
https://play.ee/website-development-contact/ 93 / 94 2.56 s / 763 ms 0.000 / 0.003

Optimization Checklist

2 of 2 passing — 2 pass · 0 warn · 0 fail · 5 n/a

Item Status Detail
Page caching plugin / CDN active Pass Caching plugin detected (WP Rocket)
Images lazy-loaded N/A No raster <img> elements found (39 SVGs, 13 placeholders excluded).
Hero image eagerly loaded N/A No raster <img> elements found (39 SVGs, 13 placeholders excluded).
Hero is a real <img> (not a CSS background-image) N/A No CSS background-images detected on raster-image-eligible elements.
Responsive images (srcset / <picture>) N/A Only 0 raster images on the page (39 SVGs, 13 placeholders excluded) — responsive-image rule does not apply.
Reasonable number of image sizes N/A Too few raster images to evaluate srcset width variety.
JS scripts not blocking in <head> Pass No render-blocking scripts in <head>.

Fixes

Priority 1: Critical

Immediate action — impacts user experience, search rankings, or site safety.

1A. Force HTTPS Redirect and Add HSTS

  • Impact: Security, Transport Layer
  • Problem: Security Headers report shows 'http://play.ee/ does not redirect to HTTPS' and 'strict-transport-security missing'.
  • Solution: Configure the web server to redirect all HTTP traffic to HTTPS (301) and send the HSTS header:
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    

1B. Enforce HTTPS and add HSTS

  • Impact: Security, Transport Layer
  • Problem: Security Headers tool reports HTTP does not redirect to HTTPS and HSTS is missing (Score 20/100).
  • Solution: Configure server to redirect all HTTP traffic to HTTPS and send HSTS header:
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

1C. Enforce HTTPS redirect and add HSTS

  • Impact: Security, Trust, SEO
  • Problem: HTTP does not redirect to HTTPS and HSTS is missing (Security Headers grade 20/100).
  • Solution: Configure server to redirect all HTTP traffic to HTTPS immediately. Add HSTS header: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

1D. Fix W3C HTML Validation Errors

  • Impact: DOM Integrity, SEO, Rendering
  • Problem: 7 validation errors including parser recovery failure at line 100 (iframe in noscript in head).
  • Solution: Move <noscript><iframe> out of <head> or ensure it is valid HTML5. Remove stray end tags (</noscript>, </head>). Fix meta tag attributes (name not allowed in this context).

1E. Fix Serious Accessibility Violations

  • Impact: WCAG 1.4.3 (Contrast), 2.4.4 (Link Purpose)
  • Problem: axe-core reports 2 serious violations: color-contrast on multiple text nodes and link-name on logo grid links.
  • Solution:
    • Increase contrast ratio for .button--tertiary and .capabilities__heading text to ≥4.5:1.
    • Add aria-label to logo grid links (e.g., <a href="" aria-label="Client Logo">).

1F. Force HTTPS redirect for all HTTP requests

  • Impact: Transport security, SEO
  • Problem: http://play.ee/web-development-in-estonia/ does not redirect to HTTPS — critical security exposure.
  • Solution: Configure server to redirect all HTTP to HTTPS:
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

1G. Add HSTS and X-Content-Type-Options headers

  • Impact: Transport security, MIME sniffing
  • Problem: HSTS and X-Content-Type-Options missing — security headers score 20/100.
  • Solution: Add to server config:
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    

1H. Fix color contrast on headings and cards

  • Impact: WCAG 1.4.3 (Contrast), Accessibility
  • Problem: axe-core reports 1 serious violation for color-contrast on multiple nodes (h1, .card__title, etc.).
  • Solution: Increase contrast ratio to at least 4.5:1 for normal text. Adjust CSS for .heading__main and .card__title:
    .heading__main { color: #333333; } /* Ensure sufficient contrast against background */
    .card__title { color: #222222; }
    

1I. Fix color contrast violations

  • Impact: WCAG 1.4.3 (Accessibility)
  • Problem: axe-core reports 1 serious violation on .heading--primary and form labels failing contrast thresholds.
  • Solution: Increase contrast ratio to ≥4.5:1 for text. For .heading--primary, darken the text color or lighten the background. For form labels, ensure sufficient contrast against the input background.

Priority 2: Important

Essential for compliance, user reach, and search visibility.

2A. Fix W3C HTML Validation Errors

  • Impact: SEO, Rendering Stability
  • Problem: W3C Validator reports 7 errors including 'Parser recovery at line 100' and 'Bad start tag in iframe in noscript in head'.
  • Solution: Correct the HTML structure in the <head> section:
    • Move <noscript><iframe>...</iframe></noscript> out of <head> or ensure it is valid HTML5.
    • Remove invalid name attribute from <meta> tags.
    • Ensure <body> tag is not closed prematurely before content.

2B. Improve Accessibility Landmarks and Link Text

  • Impact: WCAG 2.4.1, 1.3.1
  • Problem: axe-core found 'landmark-unique' and 'region' violations; HTML Inventory notes missing 'main' landmark and 'skip-to-content' link.
  • Solution:
    • Add <main id="main-content"> to wrap primary content.
    • Add a skip link at the top: <a href="#main-content" class="skip-link">Skip to content</a>.
    • Replace vague 'read more' links with descriptive text or aria-label.

2C. Fix Accessibility Contrast and Landmarks

  • Impact: WCAG 1.4.3, 1.3.1, 2.4.1
  • Problem: Axe found 1 serious color-contrast violation and PSI failed landmark-one-main (missing <main> element).
  • Solution:
    • Increase contrast ratio on .heading__main and card text to ≥4.5:1.
    • Wrap primary content in <main> tag.
    • Add a skip-to-content link at the top of the page.

2D. Resolve W3C HTML Validation Errors

  • Impact: Maintainability, Rendering Consistency
  • Problem: 7 W3C errors including parser recovery failure at line 100 (bad iframe/noscript in head).
  • Solution:
    • Move <noscript><iframe>...</iframe></noscript> out of <head> (allowed in body only).
    • Remove invalid name attribute from <meta> tags.
    • Ensure <body> tag is not duplicated.

2E. Fix Accessibility Violations

  • Impact: WCAG Compliance, Usability
  • Problem: 1 serious color-contrast violation (h1, p span) and missing main landmark/skip link.
  • Solution: Increase contrast ratio for .heading__main and p > span to ≥4.5:1. Add <main> element wrapping primary content. Add skip-to-content link at top of page.

2F. Add Explicit Image Dimensions

  • Impact: CLS, Layout Stability
  • Problem: 53 images missing width/height attributes (HTML Inventory), risking layout shifts.
  • Solution: Add width and height attributes to all <img> tags. Use CSS aspect-ratio if dimensions vary dynamically.

2G. Improve HTML Document Structure

  • Impact: SEO, Screen Reader Navigation
  • Problem: HTML Inventory shows 2 <h1> elements, missing <main> landmark, and no skip-to-content link.
  • Solution:
    • Ensure only one <h1> exists per page.
    • Wrap primary content in <main>.
    • Add a skip link at the top: <a href="#main-content" class="skip-link">Skip to content</a>.

2H. Fix color-contrast violations on headings

  • Impact: WCAG 1.4.3, accessibility
  • Problem: 21+ nodes fail color-contrast (serious axe violation) including .focus__heading > h1 and .capabilities__heading elements.
  • Solution: Increase contrast ratio to ≥4.5:1 for text. Example:
    .heading__main { color: #333333; } /* adjust to meet contrast */
    

2I. Add main landmark and skip-to-content link

  • Impact: WCAG 1.3.1, 2.4.1, accessibility
  • Problem: Document missing main landmark and skip-to-content link — 2 moderate axe violations.
  • Solution: Add skip link and main landmark:
    <a href="#main-content" class="skip-link">Skip to content</a>
    <main id="main-content">
      <!-- page content -->
    </main>
    

2J. Strengthen Content Security Policy (CSP)

  • Impact: XSS defense (User-generated content present)
  • Problem: CSP is weak (only frame-ancestors set). Site has a <textarea> form (UGC), increasing XSS risk per security rubric.
  • Solution: Implement a strict CSP with nonce/hash for scripts:
    Header set Content-Security-Policy "default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none';"
    
    Ensure all inline scripts use the nonce.

2K. Fix HTML validation errors

  • Impact: Rendering consistency, SEO
  • Problem: W3C Validator reports 8 errors including parser recovery failure at line 103 and misplaced meta/iframe tags.
  • Solution: Move <meta charset> to the first 1024 bytes. Remove <iframe> from <noscript> inside <head>. Ensure <head> closes before <body> starts.

Priority 3: Best Practice

Recommended for long-term maintainability.

3A. Add Image Dimensions and Lazy Loading

  • Impact: CLS, Performance
  • Problem: HTML Inventory shows 52 images without width/height and 52 without loading="lazy".
  • Solution:
    • Add width and height attributes to all <img> tags to reserve space.
    • Add loading="lazy" to images below the fold:
    <img src="image.svg" alt="..." width="300" height="200" loading="lazy">
    

3B. Add Explicit Dimensions to Images

  • Impact: CLS, Layout Stability
  • Problem: HTML Inventory reports 56 images without width/height attributes, risking layout shifts on load.
  • Solution: Add width and height attributes to all <img> tags:
    <img src="image.jpg" alt="..." width="300" height="200">
    

3C. Implement Strict Content Security Policy

  • Impact: XSS Defense-in-Depth
  • Problem: CSP is weak (only frame-ancestors set); default-src and object-src missing.
  • Solution: Deploy a nonce-based CSP (since no auth/payments, P3 is acceptable):
    Header set Content-Security-Policy "default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none';"
    

3D. Strengthen Content Security Policy

  • Impact: XSS Defense-in-Depth
  • Problem: CSP is weak (only frame-ancestors), though site signals indicate low auth/payment risk.
  • Solution: Implement a nonce-based CSP for future-proofing: Content-Security-Policy: script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none';

3E. Implement Content Security Policy (CSP)

  • Impact: XSS Defense-in-Depth
  • Problem: CSP is missing or weak (only frame-ancestors). Site signals indicate no auth/payments, so this is P3 per rubric.
  • Solution: Deploy a nonce-based CSP to mitigate XSS without breaking third-party scripts:
    Header set Content-Security-Policy "default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none';"
    
    Generate a unique nonce per request in PHP/WordPress.

3F. Add width/height attributes to all images

  • Impact: CLS, layout stability
  • Problem: 69 images without explicit width/height — CLS risk despite current 0.000 score.
  • Solution: Add dimensions to all <img> tags:
    <img src="image.jpg" alt="..." width="800" height="600">
    

3G. Improve CSP with nonce/strict-dynamic

  • Impact: XSS defense-in-depth
  • Problem: CSP only has frame-ancestors — missing default-src and object-src 'none'.
  • Solution: Deploy nonce-based CSP:
    Header always set Content-Security-Policy "default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none';"
    

3H. Add explicit width/height to images

  • Impact: CLS (Cumulative Layout Shift)
  • Problem: HTML inventory shows 16 images without explicit width/height attributes, risking layout shifts if CSS fails.
  • Solution: Add width and height attributes to all <img> tags to reserve space:
    <img src="image.jpg" alt="..." width="320" height="240">
    

3I. Correct heading hierarchy

  • Impact: Screen reader navigation
  • Problem: Headings skip levels (h1 → h4, h2 → h4), violating WCAG 1.3.1.
  • Solution: Adjust CSS classes or HTML tags so headings descend sequentially (e.g., h1 → h2 → h3). Do not skip levels for styling purposes; use CSS for visual sizing.
▸Raw Markdown sent to the LLM
# Site Audit — https://play.ee/
Run: 2026-07-15T07:15:20.497Z

Audited **7** of 7 discovered pages.
Average per-page audit coverage: **100%**

Pages audited:
- https://play.ee/
- https://play.ee/web-development-case-studies/
- https://play.ee/software-development-work-index/
- https://play.ee/wordpress-support-service/
- https://play.ee/web-development-in-estonia/
- https://play.ee/software-development-in-estonia/
- https://play.ee/website-development-contact/

---

# Page 1 of 7 — https://play.ee/

Run: 2026-07-15T07:15:20.566Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 20054 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **95** | 100 |
| Accessibility | 100 | 100 |
| Best Practices | 100 | 100 |
| SEO | 92 | 92 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.5 s** | 0.6 s |
| CLS | 0.002 | **0.008** |
| TBT | 0 ms | 0 ms |
| FCP | **1.96 s** | 485 ms |
| Speed Index | **2.57 s** | 485 ms |
| TTFB | **37 ms** | 9 ms |

### Priority fixes
1. **largest-contentful-paint** (low) — 2.5 s
2. **first-contentful-paint** (low) — 2.0 s
3. **network-dependency-tree-insight** (high)
4. **render-blocking-insight** (high) — Est savings of 1,230 ms
5. **unused-css-rules** (high) — Est savings of 30 KiB

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### Layout-shift sources
- div.main > footer.footer > h2.heading > span.heading__main — shift 0.002

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `largest-contentful-paint` (performance, score 0.89, weight 25) — Largest Contentful Paint — 2.5 s
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `link-text` (seo, score 0.00, weight 1) — Links do not have descriptive text — 9 links found

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 51 ms._

**Transport:**
- Final URL: https://play.ee/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 02:06:21 GMT
- expires: Wed, 15 Jul 2026 07:15:20 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 36038
- Decoded body: 220.9 KB
- Compression ratio: 0.159

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 36038
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:15:20 GMT
expires: Wed, 15 Jul 2026 07:15:20 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 02:06:21 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 699 ms._

**Scoring:** 7 errors · 0 warnings · 23 cosmetic (suppressed)

> **Validator truncated at line 100** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 100** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 97
3. **Stray end tag “noscript”.** (medium) — x1, first at line 97
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 99
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 99

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 97 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 97 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 99 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 100 `/></head>
<body class="home wp-singular page-template page-template-template-dyn`
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 100 `/></head>
<body class="home wp-singular page-template page-template-template-dyn`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1812 ms._

**Scoring:** 2 violations · 32 passes · critical 0 · serious 0 · moderate 2 · minor 0

### Priority fixes
1. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
2. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.home-hero__main`
- `.home-hero__bottom`
- `canvas`
- `.keywords__mouse`
- `.keywords__intro`
- … and 31 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 37 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 1826 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 14 network requests · 182.3 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| document | 1 | 35.2 KB |
| stylesheet | 2 | 34.2 KB |
| other | 1 | 5.5 KB |
| image | 1 | 576 B |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/fonts/fc2fa85e-cd2d-4004-930a-8adad6c60317.3bd2a5f3705d9fb438c5.woff2 (font) — 29 ms, 19.3 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/fonts/f389f79b-6013-4448-aa6a-b6fd235eab80.b91a05bafb09e626383a.woff2 (font) — 29 ms, 19.0 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/fonts/1c0243aa-c535-4d42-ac53-d6f0f74a1412.bd94708352cbb3b4863c.woff2 (font) — 29 ms, 19.3 KB
- https://play.ee/ (document) — 28 ms, 35.2 KB
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 28 ms, 10.1 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 1826 ms._

**Document:**
- Lang: en
- Title: Perfectly formed web development team - gotoAndPlay
- Canonical: https://play.ee/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 222175

**Meta tags:**
- Description: Small, agile web development team working on big ideas in close collaboration with our clients. Result driven from day one!
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 7 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time)
- Twitter tags: 3
- hreflang:
  - en → http://play.ee/
  - et → http://play.ee/et/
  - x-default → http://play.ee/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×1, h2 ×6, h3 ×5, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: we create memorable experiences with
        
                    web technologi
  - h2: Your result
  - h2: we offer
        
                    more than expected
  - h2: Üks
  - h2: meet the team of
        
                    uncommon talent
  - h2: proof to our approach are
        
                    happy clients
  - h3: Deliverables with high quality standards
  - h3: Working with gotoAndPlay is a great experience
  - h3: Speed, attitude, skills!
  - h3: Hardworking, fun & ready to adopt new technologies
  - h3: The sky is the limit
  - h2: ready when you are
            
            <span style="unicode-bidi:bidi-overr

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 52 total — **0 without alt**, **52 without width/height**, 52 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ee/wp-content/themes/gotoandplay/inc/theme/img/landscape.svg | Please turn your device sideways | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20360%20420%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 45 anchors — 33 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "read more" ×9
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2

**Forms:**
Form 1:
- text — labeled

### Priority fixes
1. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
2. **52 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)
3. **Vague link text repeated** (medium) — "read more" ×9

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (39 SVGs, 13 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (39 SVGs, 13 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (39 SVGs, 13 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 2 of 7 — https://play.ee/web-development-case-studies/

Run: 2026-07-15T07:15:20.569Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 16040 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **97** | 100 |
| Accessibility | 90 | **89** |
| Best Practices | 96 | 96 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.1 s** | 0.6 s |
| CLS | **0.003** | 0.003 |
| TBT | 0 ms | 0 ms |
| FCP | **1.95 s** | 515 ms |
| Speed Index | **1.95 s** | 517 ms |
| TTFB | 4 ms | **43 ms** |

### Priority fixes
1. **first-contentful-paint** (low) — 2.0 s
2. **network-dependency-tree-insight** (high)
3. **render-blocking-insight** (high) — Est savings of 990 ms
4. **unused-css-rules** (high) — Est savings of 32 KiB
5. **unused-javascript** (medium) — Est savings of 23 KiB

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### Layout-shift sources
- div.main > footer.footer > h2.heading > span.heading__main — shift 0.002
- div.main > footer.footer > div.footer__bottom > ul.list — shift 0.001
- div.main > footer.footer > nav.footer__nav > nav.languages — shift 0.000

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `image-size-responsive` (best-practices, score 0.00, weight 1) — Serves images with low resolution

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 43 ms._

**Transport:**
- Final URL: https://play.ee/web-development-case-studies/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/web-development-case-studies/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 13:43:22 GMT
- expires: Wed, 15 Jul 2026 07:15:20 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 28214
- Decoded body: 192.5 KB
- Compression ratio: 0.143

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/web-development-case-studies/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
accept-ranges: none
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 28214
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:15:20 GMT
expires: Wed, 15 Jul 2026 07:15:20 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 13:43:22 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 701 ms._

**Scoring:** 7 errors · 0 warnings · 23 cosmetic (suppressed)

> **Validator truncated at line 100** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 100** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 97
3. **Stray end tag “noscript”.** (medium) — x1, first at line 97
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 99
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 99

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 97 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 97 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 99 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1812 ms._

**Scoring:** 3 violations · 28 passes · critical 0 · serious 1 · moderate 2 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
3. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `h1 > .heading__main`
- `#case_study-20063 > .card__inner > .card__content > .card__meta`
- `#case_study-3610 > .card__inner > .card__content > .card__title.h4`
- `#case_study-3610 > .card__inner > .card__content > .card__meta`
- `#case_study-3420 > .card__inner > .card__content > .card__title.h4`
- … and 18 more nodes

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `h1`
- `.sidebar__title`
- `.sidebar__list`
- `.button__text`
- `#case_study-20063 > .card__inner > .card__content`
- … and 22 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 8 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 1829 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 13 network requests · 174.1 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 27.6 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 32 ms, 10.1 KB
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 32 ms, 3.0 KB
- https://play.ee/web-development-case-studies/ (document) — 26 ms, 27.6 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/fonts/fc2fa85e-cd2d-4004-930a-8adad6c60317.3bd2a5f3705d9fb438c5.woff2 (font) — 23 ms, 19.3 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/fonts/1c0243aa-c535-4d42-ac53-d6f0f74a1412.bd94708352cbb3b4863c.woff2 (font) — 23 ms, 19.3 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 1829 ms._

**Document:**
- Lang: en
- Title: Case studies of the web development company gotoAndPlay
- Canonical: https://play.ee/web-development-case-studies/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 193903

**Meta tags:**
- Description: Read about the different web development projects of gotoAndPlay. Find out more about the process, challenges and results of our work.
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 7 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time)
- Twitter tags: 3
- hreflang:
  - en → https://play.ee/web-development-case-studies/
  - et → https://play.ee/et/tehtud-tood/
  - x-default → https://play.ee/web-development-case-studies/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×1, h2 ×22, h3 ×0, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: take a look at our
        
                    featured projects
  - h2: by client
  - h2: unlocking the future of trailer sharing
  - h2: a digital glow-up for one of Estonia’s top furniture retailers
  - h2: coding a healthier future
  - h2: building cyber bridges
  - h2: navigating digital waters
  - h2: egg-citing digital transformation
  - h2: heating up the web with a new site
  - h2: bringing a breath of fresh air to office environments
  - h2: Swooshing through the ERP world using Katana
  - h2: three interwoven websites for a single pizza franchise
  - h2: A web ecosystem for the most unique cinema in town
  - h2: website for a top tier law firm
  - h2: A handcrafted sofa for your living room
  - h2: a total makeover for a business that will never cease to exist
  - h2: a modular webpage for a company that has their sight set on the future
  - h2: a high security web application for keeping an eye on your finances
  - h2: Award winning website for 21st century home
  - h2: Stress-free tutoring with tutor.id web application

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 56 total — **0 without alt**, **56 without width/height**, 56 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20300%20240%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 68 anchors — 13 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2

### Priority fixes
1. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
2. **56 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (20 SVGs, 36 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (20 SVGs, 36 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (20 SVGs, 36 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 3 of 7 — https://play.ee/software-development-work-index/

Run: 2026-07-15T07:15:37.079Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 20825 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **96** | 100 |
| Accessibility | 90 | **89** |
| Best Practices | 96 | 96 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.3 s** | 0.6 s |
| CLS | **0.041** | 0.003 |
| TBT | 0 ms | 0 ms |
| FCP | **1.98 s** | 554 ms |
| Speed Index | **1.98 s** | 554 ms |
| TTFB | **9 ms** | 8 ms |

### Priority fixes
1. **first-contentful-paint** (low) — 2.0 s
2. **network-dependency-tree-insight** (high)
3. **render-blocking-insight** (high) — Est savings of 990 ms
4. **unused-css-rules** (high) — Est savings of 32 KiB
5. **unused-javascript** (medium) — Est savings of 23 KiB

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### Layout-shift sources
- div.section__inner > div.section__content > div.h-container > div.grid — shift 0.041

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `image-size-responsive` (best-practices, score 0.00, weight 1) — Serves images with low resolution

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 53 ms._

**Transport:**
- Final URL: https://play.ee/software-development-work-index/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/software-development-work-index/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 02:22:55 GMT
- expires: Wed, 15 Jul 2026 07:15:37 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 32551
- Decoded body: 271.8 KB
- Compression ratio: 0.117

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/software-development-work-index/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 32551
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:15:37 GMT
expires: Wed, 15 Jul 2026 07:15:37 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 02:22:55 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 844 ms._

**Scoring:** 7 errors · 0 warnings · 23 cosmetic (suppressed)

> **Validator truncated at line 100** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 100** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 97
3. **Stray end tag “noscript”.** (medium) — x1, first at line 97
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 99
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 99

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 97 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 97 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 99 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1985 ms._

**Scoring:** 3 violations · 26 passes · critical 0 · serious 1 · moderate 2 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
3. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `h1 > .heading__main`
- `p:nth-child(1) > span`

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `h1`
- `.project-index__row.grid__col:nth-child(1) > .grid--middle.grid > .grid__col--last-xs.grid__col--original-sm.grid__col--sm-6`
- `.project-index__row.grid__col:nth-child(1) > .grid--middle.grid > .grid__col--sm-6.grid__col:nth-child(2) > .grid--no-wrap.grid--middle.grid > .grid__col--min.grid__col`
- `.project-index__link[href$="ehl.ee/"][target="_blank"]`
- `.has-link.project-index__row.grid__col:nth-child(2) > .grid--middle.grid > .grid__col--last-xs.grid__col--original-sm.grid__col--sm-6 > .project-index__heading`
- … and 147 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 9 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 2002 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 13 network requests · 178.3 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 31.8 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 27 ms, 10.1 KB
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 27 ms, 3.0 KB
- https://play.ee/software-development-work-index/ (document) — 23 ms, 31.8 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (script) — 22 ms, 31.5 KB
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (script) — 21 ms, 3.6 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 2002 ms._

**Document:**
- Lang: en
- Title: High-quality software development – from idea to launch
- Canonical: https://play.ee/software-development-work-index/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 275014

**Meta tags:**
- Description: Our focus is on web application, website and software development, utilizing top-tier technologies such as Laravel, React, and Node.js.
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 7 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time)
- Twitter tags: 3
- hreflang:
  - en → https://play.ee/software-development-work-index/
  - et → https://play.ee/et/tarkvaraarendus-saavutuste-indeks/
  - x-default → https://play.ee/software-development-work-index/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×1, h2 ×30, h3 ×0, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: highlights from the
        
                    last couple of years
  - h2: Future-proof software development for Tallink
  - h2: Built on years of trust – the EHL web transformation
  - h2: Web experience capturing the spirit and energy of Tallinn City Theatre
  - h2: Building the future of Estonian engineering with a next-gen web experience
  - h2: New website for a new perspective
  - h2: Risk management portal for IUTE
  - h2: Unlocking the future of trailer sharing
  - h2: Smart web for smart lockers
  - h2: WordPress website for Forus
  - h2: A new website for Coop Pank that offers the best experience for their customers
  - h2: Bringing together cybersecurity experts and stakeholders
  - h2: Auctions platform MVP for Foxway
  - h2: Going beyond the benchmark with Katana website
  - h2: Web application for a green energy marketplace
  - h2: Custom tailored PIM for Telia Eesti
  - h2: Back-office system for arthouse cinema
  - h2: Updating a webpage for most stylish quarter in Tallinn
  - h2: Amplifying the future with Low Noise Factory
  - h2: Just like Airbnb, but for trailers

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 53 total — **0 without alt**, **53 without width/height**, 53 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 93 anchors — 75 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "visit the website" ×21
- "visit website" ×21
- "read more about the project" ×15
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "read the case study" ×3
- "read case study" ×3

### Priority fixes
1. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
2. **53 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)
3. **Vague link text repeated** (medium) — "read more about the project" ×15, "read more about futuclass" ×3

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (24 SVGs, 29 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (24 SVGs, 29 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (24 SVGs, 29 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 4 of 7 — https://play.ee/wordpress-support-service/

Run: 2026-07-15T07:15:57.578Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 12930 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **97** | 100 |
| Accessibility | 91 | 91 |
| Best Practices | 100 | 100 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.3 s** | 0.5 s |
| CLS | **0.017** | 0.003 |
| TBT | 0 ms | 0 ms |
| FCP | **1.95 s** | 526 ms |
| Speed Index | **1.95 s** | 526 ms |
| TTFB | 8 ms | 8 ms |

### Priority fixes
1. **first-contentful-paint** (low) — 2.0 s
2. **network-dependency-tree-insight** (high)
3. **render-blocking-insight** (high) — Est savings of 1,050 ms
4. **unused-css-rules** (high) — Est savings of 31 KiB
5. **unused-javascript** (medium) — Est savings of 23 KiB

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### Layout-shift sources
- div.canvas__inner > section.section > div.section__inner > div.section__content — shift 0.017

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 39 ms._

**Transport:**
- Final URL: https://play.ee/wordpress-support-service/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/wordpress-support-service/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 09:05:44 GMT
- expires: Wed, 15 Jul 2026 07:15:57 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 31200
- Decoded body: 184.3 KB
- Compression ratio: 0.165

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/wordpress-support-service/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 31200
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:15:57 GMT
expires: Wed, 15 Jul 2026 07:15:57 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 09:05:44 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 702 ms._

**Scoring:** 7 errors · 0 warnings · 30 cosmetic (suppressed)

> **Validator truncated at line 107** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 107** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 104
3. **Stray end tag “noscript”.** (medium) — x1, first at line 104
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 106
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 106

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 104 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 104 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 106 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 106 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 106 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 107 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 107 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1995 ms._

**Scoring:** 4 violations · 32 passes · critical 0 · serious 2 · moderate 2 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **link-name** (high) — Links must have discernible text
3. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
4. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `.button--tertiary > .button__inner > .button__text`
- `.grid__col--md-4.capabilities__grid-col.grid__col--sm-6:nth-child(1) > .heading--h5.capabilities__heading.h5 > .heading__small`
- `.grid__col--md-4.capabilities__grid-col.grid__col--sm-6:nth-child(2) > .heading--h5.capabilities__heading.h5 > .heading__small`
- `.grid__col--md-4.capabilities__grid-col.grid__col--sm-6:nth-child(3) > .heading--h5.capabilities__heading.h5 > .heading__small`
- `.grid__col--md-4.capabilities__grid-col.grid__col--sm-6:nth-child(4) > .heading--h5.capabilities__heading.h5 > .heading__small`
- … and 10 more nodes

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `.logo-grid__row.js-in-viewport:nth-child(1) > .logo-grid__item:nth-child(1) > .logo-grid__link[href=""][rel="noopener"]`
- `.logo-grid__row.js-in-viewport:nth-child(1) > .logo-grid__item:nth-child(2) > .logo-grid__link[href=""][rel="noopener"]`
- `.logo-grid__row.js-in-viewport:nth-child(1) > .logo-grid__item:nth-child(3) > .logo-grid__link[href=""][rel="noopener"]`
- `.logo-grid__row.js-in-viewport:nth-child(2) > .logo-grid__item:nth-child(1) > .logo-grid__link[href=""][rel="noopener"]`
- `.logo-grid__row.js-in-viewport:nth-child(2) > .logo-grid__item:nth-child(2) > .logo-grid__link[href=""][rel="noopener"]`
- … and 4 more nodes

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.contact-hero__intro > h1`
- `.intro__content > p:nth-child(2)`
- `p:nth-child(3)`
- `.button--tertiary`
- `canvas`
- … and 95 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 14 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 2007 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 24 network requests · 197.8 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 30.5 KB |
| image | 11 | 20.8 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 27 ms, 3.0 KB
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 27 ms, 10.1 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (script) — 25 ms, 31.5 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js (script) — 24 ms, 1.0 KB
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (script) — 24 ms, 3.6 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 2007 ms._

**Document:**
- Lang: en
- Title: WordPress support service
- Canonical: https://play.ee/wordpress-support-service/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 187428

**Meta tags:**
- Description: From ongoing WordPress support to health monitoring and expert fixes, we take care of your website so you can spend more time building your business.
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 13 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time, og:image, og:image:secure_url, og:image:width, og:image:height, og:image:alt, og:image:type)
- Twitter tags: 4
- hreflang:
  - en → https://play.ee/wordpress-support-service/
  - et → https://play.ee/et/tugiteenus/
  - x-default → https://play.ee/wordpress-support-service/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×2, h2 ×16, h3 ×14, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: Your worry-free
        
                    WordPress website
  - h2: Why choose our
        
                    WordPress support service
  - h3: #1
        
                    peace of mind
  - h3: #2
        
                    security first
  - h3: #3
        
                    expert team on-call
  - h3: #4
        
                    performance wins
  - h3: #5
        
                    save money
  - h3: #6
        
                    monthly health reports
  - h3: #7
        
                    collaboration
  - h3: #8
        
                    extensive network
  - h3: #9
        
                    top notch tools
  - h2: service by professionals who
        
                    build websites for a l
  - h2: customizable & transparent
        
                    Pricing
  - h2: <Basic/>
  - h2: <Advanced/>
  - h2: <Pro/>
  - h2: five-step
        
                    onboarding process
  - h1: additional services
        
                    to upgrade your online presence
  - h2: UX/UI audit
  - h2: WCAG audit

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 28 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 31 total — **0 without alt**, **31 without width/height**, 31 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | Expert WordPress support service | _n/a_ | _n/a_ | ✗ |
| p-content/themes/gotoandplay/inc/theme/img/line-1-mobile.svg | line-1 | _n/a_ | _n/a_ | ✗ |
| ay.ee/wp-content/themes/gotoandplay/inc/theme/img/line-1.svg | line-1 | _n/a_ | _n/a_ | ✗ |
| p-content/themes/gotoandplay/inc/theme/img/line-2-mobile.svg | line-2 | _n/a_ | _n/a_ | ✗ |
| ay.ee/wp-content/themes/gotoandplay/inc/theme/img/line-2.svg | line-2 | _n/a_ | _n/a_ | ✗ |
| p-content/themes/gotoandplay/inc/theme/img/line-3-mobile.svg | line-3 | _n/a_ | _n/a_ | ✗ |
| ay.ee/wp-content/themes/gotoandplay/inc/theme/img/line-3.svg | line-3 | _n/a_ | _n/a_ | ✗ |
| p-content/themes/gotoandplay/inc/theme/img/line-4-mobile.svg | line-4 | _n/a_ | _n/a_ | ✗ |
| ay.ee/wp-content/themes/gotoandplay/inc/theme/img/line-4.svg | line-4 | _n/a_ | _n/a_ | ✗ |
| p-content/themes/gotoandplay/inc/theme/img/line-5-mobile.svg | line-5 | _n/a_ | _n/a_ | ✗ |
| ay.ee/wp-content/themes/gotoandplay/inc/theme/img/line-5.svg | line-5 | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 56 anchors — 17 external, 2 preconnect, 0 preload.

Vague repeated link text:
- "get in touch" ×13
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2

### Priority fixes
1. **Document has 2 <h1> elements** (medium) — A page should have exactly one h1; multiple h1s break document outline
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **31 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (24 SVGs, 7 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (24 SVGs, 7 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (24 SVGs, 7 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 5 of 7 — https://play.ee/web-development-in-estonia/

Run: 2026-07-15T07:16:18.655Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 18554 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **93** | 100 |
| Accessibility | 94 | **93** |
| Best Practices | 100 | 100 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.6 s** | 0.5 s |
| CLS | 0.000 | **0.005** |
| TBT | 0 ms | 0 ms |
| FCP | **1.99 s** | 486 ms |
| Speed Index | **3.92 s** | 535 ms |
| TTFB | 5 ms | **36 ms** |

### Priority fixes
1. **largest-contentful-paint** (low) — 2.6 s
2. **speed-index** (low) — 3.9 s
3. **first-contentful-paint** (low) — 2.0 s
4. **network-dependency-tree-insight** (high)
5. **render-blocking-insight** (high) — Est savings of 1,210 ms

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `largest-contentful-paint` (performance, score 0.87, weight 25) — Largest Contentful Paint — 2.6 s
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `speed-index` (performance, score 0.82, weight 10) — Speed Index — 3.9 s
- `first-contentful-paint` (performance, score 0.84, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 38 ms._

**Transport:**
- Final URL: https://play.ee/web-development-in-estonia/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/web-development-in-estonia/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 02:22:20 GMT
- expires: Wed, 15 Jul 2026 07:16:18 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 33711
- Decoded body: 223.2 KB
- Compression ratio: 0.147

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/web-development-in-estonia/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 33711
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:16:18 GMT
expires: Wed, 15 Jul 2026 07:16:18 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 02:22:20 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 712 ms._

**Scoring:** 7 errors · 0 warnings · 23 cosmetic (suppressed)

> **Validator truncated at line 100** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 100** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 97
3. **Stray end tag “noscript”.** (medium) — x1, first at line 97
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 99
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 99

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 97 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 97 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 99 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 99 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 100 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 2059 ms._

**Scoring:** 3 violations · 32 passes · critical 0 · serious 1 · moderate 2 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
3. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `.focus__heading > h1 > .heading__main`
- `.capabilities__grid-col.grid__col--sm-6.grid__col--md-4:nth-child(1) > .capabilities__heading.heading--h5.h5 > .heading__small`
- `.capabilities__grid-col.grid__col--sm-6.grid__col--md-4:nth-child(2) > .capabilities__heading.heading--h5.h5 > .heading__small`
- `.capabilities__grid-col.grid__col--sm-6.grid__col--md-4:nth-child(3) > .capabilities__heading.heading--h5.h5 > .heading__small`
- `.capabilities__grid-col.grid__col--sm-6.grid__col--md-4:nth-child(4) > .capabilities__heading.heading--h5.h5 > .heading__small`
- … and 21 more nodes

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.section--page-intro`
- `.capabilities`
- `.alliance`
- `.mentoring > .section__inner > .section__content > .h-container > .intro`
- `.partners-logos`
- … and 59 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 88 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 2074 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 14 network requests · 197.5 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 32.9 KB |
| image | 1 | 18.1 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 26 ms, 10.1 KB
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 26 ms, 3.0 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (script) — 23 ms, 31.5 KB
- https://play.ee/web-development-in-estonia/ (document) — 22 ms, 32.9 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js (script) — 20 ms, 1.0 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 2074 ms._

**Document:**
- Lang: en
- Title: Expert web development in Estonia and worldwide
- Canonical: https://play.ee/web-development-in-estonia/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 225609

**Meta tags:**
- Description: Premium web development in Estonia and beyond. We provide a full range of services, from building simple websites to complex web applications.
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 7 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time)
- Twitter tags: 3
- hreflang:
  - en → https://play.ee/web-development-in-estonia/
  - et → https://play.ee/et/veebiarendus-eestis/
  - x-default → https://play.ee/web-development-in-estonia/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×2, h2 ×28, h3 ×37, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: our
        
                    strong suit
  - h2: we love
        
                    web apps
  - h2: we make awesome
        
                    websites
  - h2: we validate ideas by
        
                    prototyping
  - h2: how it's done
        
                    our way
  - h3: 01
        
                    discover
  - h3: 02
        
                    research
  - h3: 03
        
                    plan
  - h3: 04
        
                    create and iterate
  - h3: 05
        
                    launch
  - h3: 06
        
                    support
  - h2: we are part of
        
                    play & nope alliance
  - h2: we believe in learning from
        
                    each other
  - h2: we love our
        
                    partners
  - h2: follow our
        
                    journey
  - h3: GOTOANDPLAY WAS FOUNDED
  - h3: THE TEAM IS GROWING
  - h3: FIRST BIG PROJECT
  - h3: FIRST BIG CLIENT
  - h3: WE SNATCHED PLAY.EE

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 32 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 69 total — **0 without alt**, **69 without width/height**, 69 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 0%2Fsvg%22%20viewBox%3D%220%200%20230%2080%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 62 anchors — 46 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2

### Priority fixes
1. **Document has 2 <h1> elements** (medium) — A page should have exactly one h1; multiple h1s break document outline
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **69 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (54 SVGs, 15 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (54 SVGs, 15 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (54 SVGs, 15 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 6 of 7 — https://play.ee/software-development-in-estonia/

Run: 2026-07-15T07:16:22.886Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: no
- E-commerce: no

## PageSpeed Insights
_Captured in 11213 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **96** | 100 |
| Accessibility | 91 | **90** |
| Best Practices | 100 | 100 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.5 s** | 0.6 s |
| CLS | 0.003 | **0.004** |
| TBT | 0 ms | 0 ms |
| FCP | **1.98 s** | 554 ms |
| Speed Index | **1.98 s** | 554 ms |
| TTFB | 7 ms | **39 ms** |

### Priority fixes
1. **first-contentful-paint** (low) — 2.0 s
2. **network-dependency-tree-insight** (high)
3. **render-blocking-insight** (high) — Est savings of 1,240 ms
4. **unused-css-rules** (high) — Est savings of 32 KiB
5. **unused-javascript** (medium) — Est savings of 23 KiB

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### Layout-shift sources
- div.main > footer.footer > h2.heading > span.heading__main — shift 0.003

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 37 ms._

**Transport:**
- Final URL: https://play.ee/software-development-in-estonia/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/software-development-in-estonia/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 08:45:20 GMT
- expires: Wed, 15 Jul 2026 07:16:22 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 27786
- Decoded body: 128.9 KB
- Compression ratio: 0.211

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/software-development-in-estonia/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 27786
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:16:22 GMT
expires: Wed, 15 Jul 2026 07:16:22 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 08:45:20 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 584 ms._

**Scoring:** 7 errors · 0 warnings · 30 cosmetic (suppressed)

> **Validator truncated at line 107** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 107** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 104
3. **Stray end tag “noscript”.** (medium) — x1, first at line 104
4. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 106
5. **Element “meta” is missing one or more of the following attributes: “itemprop”, “property”.** (medium) — x1, first at line 106

### Issue groups
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 104 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 104 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 106 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 106 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 106 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 107 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 107 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1435 ms._

**Scoring:** 3 violations · 28 passes · critical 0 · serious 1 · moderate 2 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
3. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `h1 > .heading__main`
- `.card__title`
- `.how-we-do__intro > .heading--primary > .heading__main`
- `.grid__col.grid__col--sm-6.grid__col--md-4:nth-child(1) > .capabilities__heading.heading--h5.h5 > .heading__small`
- `.grid__col.grid__col--sm-6.grid__col--md-4:nth-child(2) > .capabilities__heading.heading--h5.h5 > .heading__small`
- … and 4 more nodes

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `h1`
- `.card-list__aside`
- `.card__content`
- `section[data-theme="white"]:nth-child(2) > .section__inner > .section__content > .h-container`
- `.carousel__slide:nth-child(1) > .testimonial.carousel__slide-inner > .testimonial__inner.text > .testimonial__title`
- … and 37 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 9 nodes
- [<video> elements must have captions](https://dequeuniversity.com/rules/axe/4.11/video-caption?application=playwright) — 7 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 1444 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 14 network requests · 191.7 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 5 | 49.2 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 27.1 KB |
| image | 1 | 18.1 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 29 ms, 3.0 KB
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 26 ms, 10.1 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js (script) — 23 ms, 1.0 KB
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (script) — 23 ms, 3.6 KB
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (script) — 23 ms, 31.5 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 1444 ms._

**Document:**
- Lang: en
- Title: Software development in Estonia – Laravel, React, Node.js development
- Canonical: https://play.ee/software-development-in-estonia/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 131344

**Meta tags:**
- Description: Looking for a challenge? Our daily life revolves around software development in Estonia and beyond – specializing in Laravel, React, and Node.js.
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 13 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time, og:image, og:image:secure_url, og:image:width, og:image:height, og:image:alt, og:image:type)
- Twitter tags: 4
- hreflang:
  - en → https://play.ee/software-development-in-estonia/
  - et → https://play.ee/et/tarkvaraarendus-eestis-karjaar/
  - x-default → https://play.ee/software-development-in-estonia/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×1, h2 ×6, h3 ×21, h4 ×0, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: join our
        
                    team
  - h2: looking for
  - h2: full-stack developer
  - h2: thoughts from
        
                    our team
  - h3: Support and Flexibility
  - h3: Possibility to work and have an adventure
  - h3: Excoticism at your fingertips
  - h3: Working here is diverse and exciting
  - h3: I feel like the company’s values align with mine
  - h3: gotoAndUniversity
  - h3: I feel I can be 100% me
  - h2: how
        
                    we do things
  - h3: for us
        
                    impossible is possible
  - h3: we inspire
        
                    each other
  - h3: work hard
        
                    play hard
  - h3: we do
        
                    what we love
  - h3: we like
        
                    to be curious
  - h3: key to success is
        
                    quality and efficiency
  - h2: what you get
        
                    with us
  - h3: 01
        
                    exciting projects

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 3 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 16 total — **0 without alt**, **16 without width/height**, 16 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| 00%2Fsvg%22%20viewBox%3D%220%200%2070%2070%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | tarkvaraarendus eestis ja mujal maailmas | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20320%20320%22%3E%3C%2Fsvg%3E | Looking for a web development intern at  | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20352%20264%22%3E%3C%2Fsvg%3E | full-stack development / full-stack aren | _n/a_ | _n/a_ | ✗ |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20320%20320%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20320%20320%22%3E%3C%2Fsvg%3E | _(empty)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 32 anchors — 14 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2

### Priority fixes
1. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
2. **16 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (12 SVGs, 4 placeholders excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (12 SVGs, 4 placeholders excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (12 SVGs, 4 placeholders excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 7 of 7 — https://play.ee/website-development-contact/

Run: 2026-07-15T07:16:44.603Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — <textarea> in a form
- E-commerce: no

## PageSpeed Insights
_Captured in 21284 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **93** | 94 |
| Accessibility | 94 | 94 |
| Best Practices | 100 | 100 |
| SEO | 100 | 100 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **2.6 s** | 0.8 s |
| CLS | 0.000 | **0.003** |
| TBT | 0 ms | **187 ms** |
| FCP | **1.98 s** | 529 ms |
| Speed Index | **4.13 s** | 1.01 s |
| TTFB | **42 ms** | 40 ms |

### Priority fixes
1. **largest-contentful-paint** (low) — 2.6 s
2. **speed-index** (low) — 4.1 s
3. **first-contentful-paint** (low) — 2.0 s
4. **network-dependency-tree-insight** (high)
5. **render-blocking-insight** (high) — Est savings of 1,300 ms

### Findings (mobile)

#### Unused JavaScript
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js — 23 KB wasted

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `largest-contentful-paint` (performance, score 0.88, weight 25) — Largest Contentful Paint — 2.6 s
- `heading-order` (accessibility, score 0.00, weight 3) — Heading elements are not in a sequentially-descending order
- `speed-index` (performance, score 0.79, weight 10) — Speed Index — 4.1 s
- `first-contentful-paint` (performance, score 0.85, weight 10) — First Contentful Paint — 2.0 s
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 35 ms._

**Transport:**
- Final URL: https://play.ee/website-development-contact/
- Status: 200
- Redirected: false
- HTTPS redirect: ✗ http://play.ee/website-development-contact/ does not redirect to HTTPS (target: none)

**Caching:**
- cache-control: `max-age=0`
- etag: n/a
- last-modified: Thu, 02 Jul 2026 03:53:03 GMT
- expires: Wed, 15 Jul 2026 07:16:44 GMT
- pragma: n/a
- vary: Accept-Encoding

**Compression:**
- content-encoding: gzip
- content-length: 27962
- Decoded body: 106.5 KB
- Compression ratio: 0.256

### Priority fixes
1. **HTTP does not redirect to HTTPS** (high) — http://play.ee/website-development-contact/ does not redirect to HTTPS
2. **strict-transport-security missing** (high) — Add HSTS with max-age >= 1 year, includeSubDomains, and preload
3. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
4. **x-content-type-options missing** (medium) — Send X-Content-Type-Options: nosniff
5. **referrer-policy missing** (low) — Set a Referrer-Policy such as strict-origin-when-cross-origin
6. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
7. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
8. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
9. **x-permitted-cross-domain-policies missing** (low) — Set to none to prevent Flash/PDF cross-domain requests
10. **server header discloses technology** (low) — Server: Apache

### Findings

#### Tracked headers
- **strict-transport-security** (missing, high)
- **content-security-policy** (weak, high) `frame-ancestors 'self';` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (present, medium) `SAMEORIGIN`
- **x-content-type-options** (missing, medium)
- **referrer-policy** (missing, low)
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (missing, low)

#### Info disclosure
- Server: `Apache`
- X-Powered-By: `PHP/8.3.32`

#### All response headers
```
cache-control: max-age=0
connection: Upgrade, Keep-Alive
content-encoding: gzip
content-length: 27962
content-security-policy: frame-ancestors 'self';
content-type: text/html; charset=UTF-8
date: Wed, 15 Jul 2026 07:16:44 GMT
expires: Wed, 15 Jul 2026 07:16:44 GMT
keep-alive: timeout=5, max=100
last-modified: Thu, 02 Jul 2026 03:53:03 GMT
server: Apache
upgrade: h2,h2c
vary: Accept-Encoding
x-frame-options: SAMEORIGIN
x-powered-by: PHP/8.3.32
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 717 ms._

**Scoring:** 8 errors · 0 warnings · 23 cosmetic (suppressed)

> **Validator truncated at line 103** — the Nu validator stopped after hitting its internal error budget; score against the errors above, NOT as a fatal parse failure: Cannot recover after last error. Any further errors will be ignored.

### Priority fixes
1. **Parser recovery at line 103** (high) — Cannot recover after last error. Any further errors will be ignored.
2. **A “charset” attribute on a “meta” element found after the first 1024 bytes.** (medium) — x1, first at line 6
3. **Bad start tag in “iframe” in “noscript” in “head”.** (medium) — x1, first at line 100
4. **Stray end tag “noscript”.** (medium) — x1, first at line 100
5. **Attribute “name” not allowed on element “meta” at this point.** (medium) — x1, first at line 102

### Issue groups
- (×1) [error] A “charset” attribute on a “meta” element found after the first 1024 bytes. — first at line 6 `charset="utf-8"><script>if(na`
- (×1) [error] Bad start tag in “iframe” in “noscript” in “head”. — first at line 100 `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3P64XMJ"`
- (×1) [error] Stray end tag “noscript”. — first at line 100 `></iframe></noscript><!-- E`
- (×1) [error] Attribute “name” not allowed on element “meta” at this point. — first at line 102 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Element “meta” is missing one or more of the following attributes: “itemprop”, “property”. — first at line 102 `<meta name="generator" content="WP Rocket 3.22.0.3" data-wpr-features="wpr_delay`
- (×1) [error] Stray end tag “head”. — first at line 102 `esktop" /></head>
<body`
- (×1) [error] Start tag “body” seen but an element of the same type was already open. — first at line 103 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `
- (×1) [error] Cannot recover after last error. Any further errors will be ignored. — first at line 103 `/></head>
<body class="wp-singular page-template page-template-template-dynamic `

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 1238 ms._

**Scoring:** 4 violations · 38 passes · critical 0 · serious 1 · moderate 3 · minor 0

### Priority fixes
1. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
2. **heading-order** (medium) — Heading levels should only increase by one
3. **landmark-unique** (medium) — Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
4. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `.heading--primary > .heading__main`
- `label[for="input_1_1"]`
- `label[for="input_1_3"]`
- `label[for="input_1_4"]`
- `#field_1_7 > span`
- … and 4 more nodes

#### `heading-order` (moderate)
[Heading levels should only increase by one](https://dequeuniversity.com/rules/axe/4.11/heading-order?application=playwright)
- `.section--page-intro > .section__inner > .section__content > .h-container > .grid > .grid__col--sm-4.text.grid__col:nth-child(1) > h4`
- `#location > .section__inner > .section__content > .h-container > .grid > .grid__col--md-3.grid__col--sm-4.text > h4:nth-child(1)`
- `.location:nth-child(5) > .section__inner > .section__content > .h-container > .grid > .grid__col--md-3.grid__col--sm-4.text > h4`

#### `landmark-unique` (moderate)
[Landmarks should have a unique role or role/label/title (i.e. accessible name) combination](https://dequeuniversity.com/rules/axe/4.11/landmark-unique?application=playwright)
- `.header__nav`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.section--page-intro > .section__inner > .section__content > .h-container`
- `canvas`
- `.heading--primary`
- `#field_1_1`
- `#field_1_3`
- … and 12 more nodes

### Incomplete (axe could not determine)
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 26 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 1246 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 14 network requests · 174.7 KB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| font | 3 | 57.6 KB |
| script | 6 | 50.1 KB |
| stylesheet | 2 | 34.2 KB |
| document | 1 | 27.3 KB |
| other | 1 | 5.5 KB |
| xhr | 1 | 0 B |

**Third-party origins (by bytes):**
- https://cdn.jsdelivr.net — 2 requests, 13.2 KB
- https://fast.fonts.net — 2 requests, 0 B

**Slowest requests (top 5):**
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (script) — 30 ms, 31.5 KB
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (script) — 30 ms, 3.0 KB
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (script) — 30 ms, 10.1 KB
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (script) — 29 ms, 3.6 KB
- https://play.ee/website-development-contact/ (document) — 21 ms, 27.3 KB

### Findings

#### Console events
- [warning] Couldn't load preload assets:  

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 1246 ms._

**Document:**
- Lang: en
- Title: 100% expert software and website development services
- Canonical: https://play.ee/website-development-contact/
- Viewport: width=device-width, initial-scale=1
- Charset: UTF-8
- HTML bytes: 108389

**Meta tags:**
- Description: Looking for a digital partner? We specialize in top-tier software, e-commerce, and website development. We bring your boldest ideas to life!
- Robots: follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large
- Theme color: #ffffff
- Open Graph tags: 7 (og:locale, og:type, og:title, og:description, og:url, og:site_name, og:updated_time)
- Twitter tags: 3
- hreflang:
  - en → https://play.ee/website-development-contact/
  - et → https://play.ee/et/veebilehe-arendus-kontakt/
  - x-default → https://play.ee/website-development-contact/
- JSON-LD: 1 blocks (1 valid) — types: Unknown

**Heading outline:**
- Counts: h1 ×1, h2 ×5, h3 ×0, h4 ×6, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: take the first steps
        
                    to play
  - h4: new business
  - h4: careers
  - h4: support
  - h2: feel free to
        
                    contact us
  - h2: we are part of
        
                    play & nope alliance
  - h2: we live, work & play in
        
                    tartu, estonia
  - h4: location
  - h4: general
  - h2: but also present in
        
                    tallinn, estonia
  - h4: location
  - h2: ready when you are
            
            <span style="unicode-bidi:bidi-overr
- Skips:
  - h1 → h4 after "take the first steps
        
                    to play"
  - h2 → h4 after "we live, work & play in
        
                    tartu, "
  - h2 → h4 after "but also present in
        
                    tallinn, es"

**Landmarks:**
- nav: present
- main: **missing**
- header: present
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 41 total — 4 defer, 1 async, 1 render-blocking. Speculation rules: yes.

External scripts (first 15):
- https://cdn.jsdelivr.net/gh/orestbida/iframemanager@1.3.0/dist/iframemanager.js (defer)
- https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.umd.js (defer)
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/runtime.30d3b226dcf211e512b1.min.js
- https://play.ee/wp-content/themes/gotoandplay/inc/theme/js/jquery.bfe1bb19d13b3c17b682.min.js (defer)
- https://play.ee/wp-content/plugins/gravityforms/js/jquery.json.min.js (defer)
- https://play.ee/wp-content/plugins/wp-rocket/assets/js/wpr-beacon.min.js (async)

**Stylesheets:** 1 external, 3 inline (9.4 KB)

**Images:** 2 total — **0 without alt**, **2 without width/height**, 2 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| ;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== | _(empty)_ | _n/a_ | _n/a_ | ✗ |
| %2Fsvg%22%20viewBox%3D%220%200%20425%20185%22%3E%3C%2Fsvg%3E | website developemt / veebilehe arendus | _n/a_ | _n/a_ | ✗ |

**Links:** 36 anchors — 21 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "view our instagram feed" ×3
- "visit our facebook page" ×3
- "visit our linkedin page" ×3
- "eng" ×3
- "est" ×3
- "styleguide" ×2
- "privacy policy" ×2
- "navigate to us" ×2

**Forms:**
Form 1:
- hidden — **no label**
- text — labeled
- email — labeled
- textarea — labeled
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**
- hidden — **no label**

### Priority fixes
1. **Heading level skips** (medium) — h1→h4 after "take the first steps
        
          "; h2→h4 after "we live, work & play in
        
       "; h2→h4 after "but also present in
        
           "
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **2 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 0 fail · 5 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✓ pass | Caching plugin detected (WP Rocket) |
| Images lazy-loaded | – n/a | No raster <img> elements found (1 SVG, 1 placeholder excluded). |
| Hero image eagerly loaded | – n/a | No raster <img> elements found (1 SVG, 1 placeholder excluded). |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | – n/a | Only 0 raster images on the page (1 SVG, 1 placeholder excluded) — responsive-image rule does not apply. |
| Reasonable number of image sizes | – n/a | Too few raster images to evaluate srcset width variety. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Page caching plugin / CDN active:
  - `HTML markers: WP Rocket`
  - `generator: WP Rocket 3.22.0.3`

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).