Web Quality Audit: Perfora (perforacare.com)
Website: https://perforacare.com/ | Date: 2026-09-07 | Platform: Shopify (OS 2.0, GoKwik checkout, Cloudflare) | Industry: D2C Oral Care (India)
Business context: Perfora is a Gurugram-based D2C oral-care brand (founded 2021; Shark Tank S2; ~₹70 Cr FY25 revenue). Audience is 96.1% phone / 3.9% desktop / 0% tablet (Aug 2026 CrUX) — an extreme mobile-first store where phone UX and speed are the entire game. Full context in business-analysis.md.
Executive Summary
Perfora's storefront is technically functional and SEO-literate but performance-heavy and accessibility-thin. The mobile Lighthouse Performance score is 31/100 (Poor) driven by a 6.7s LCP and 2,590ms Total Blocking Time on emulated mid-range mobile — yet real-world CrUX field data tells a better story (LCP ~2.2s Good, INP ~207–218ms Needs Improvement, CLS 0.03–0.05 Good). The gap means real users on decent devices are OK on loading, but interactivity (INP) is the one metric failing in the field, and the lab result shows how badly it degrades on slower hardware/network. SEO is strong (92), structured data is well-implemented on products/blogs, and security headers are solid. The biggest brand-risk finding is AI-generated product imagery (ChatGPT_Image_*) used on hero/conversion carousel tiles — acceptable for a science-led FMCG but worth a brand-authenticity review given Perfora's "clinically proven / design-led" positioning.
Score Card
| Category | Mobile Score | Desktop Score | Grade |
|---|---|---|---|
| Performance | 31 | not captured (lab hung) | 🔴 |
| Accessibility | 79 | not captured | 🟡 |
| Best Practices | 73 | not captured | 🟡 |
| SEO | 92 | not captured | 🟢 |
| Overall (mobile) | ~69/100 (weighted) | — | 🟡 |
Lab desktop run did not complete in the headless browser (a known flake — the mobile run also took ~3 min). All desktop numbers below are therefore inferred from mobile lab + field data, not measured. Given the 24:1 mobile:desktop audience ratio, this is a minor gap.
Headline verdict: Fix INP (real-user interactivity failure) and the mobile LCP/lab gap first — those are the only metrics Google is actively down-ranking the site on. Then close the accessibility and schema-coverage gaps.
1. Performance Audit
1.1 CrUX Real-World Field Data
Core Web Vitals Assessment: Needs Improvement on mobile (the only platform with meaningful traffic). INP is the failing metric; LCP and CLS are Good. Desktop/tablet volumes are too small to assess meaningfully.
Source: CrUX via cruxvis.withgoogle.com, origin https://perforacare.com, "Core Web Vitals of this URL on phones," summary as of 2026-08-29.
| Metric | Latest field value (2026-08-29) | Threshold (Good / Poor) | Rating |
|---|---|---|---|
| LCP | ~2,244 ms (trend 2.2–3.4s over the year) | ≤2,500 / >4,000 ms | 🟢 Good (trending toward boundary) |
| INP | ~207–218 ms | ≤200 / >500 ms | 🟡 Needs Improvement |
| CLS | 0.03 (Cuxt summary 0.05) | ≤0.10 / >0.25 | 🟢 Good but regressing |
Field trend (phone), weekly LCP / INP / CLS:
- Nov 2025: 3,358 ms / 257 ms / 0.08
- Feb 2026: 3,035 ms / 187 ms / 0.03
- May 2026: 2,974 ms / 195 ms / 0.03
- Aug 2026: 2,244 ms / 207 ms / 0.03
Interpretation: Loading performance improved ~33% over the year (3.4s→2.2s LCP) — good engineering work. But INP climbed back above the 200ms Good threshold in mid-2026 (180ms Feb → 207ms Aug), i.e. the site got less responsive as features (GoKwik, Freshchat, Verifast chatbot, Netcore, Clarity) were added. CLS is Good-but-regressing (0.03→0.05), consistent with the 73 empty-alt images and lazy-loaded carousels causing late layout shifts.
1.2 Core Web Vitals (Lighthouse Lab Data — Mobile)
Source: PageSpeed Insights, report 2026-09-07 08:19 UTC, Lighthouse 13.4.1, emulated Moto G Power, Slow-4G throttling.
| Metric | Mobile Lab | Mobile Threshold | Rating |
|---|---|---|---|
| FCP | 3.3 s | ≤1.8 / >3.0 s | 🔴 Poor |
| LCP | 6.7 s | ≤2.5 / >4.0 s | 🔴 Poor (2.7× Good) |
| TBT | 2,590 ms | ≤200 / >600 ms | 🔴 Poor (12.9× Good) |
| CLS | 0.065 | ≤0.10 / >0.25 | 🟢 Good |
| Speed Index | 13.2 s | ≤3.4 / >5.8 s | 🔴 Poor |
Mobile vs Desktop gap: Not measured (desktop lab hung). The mobile lab result is materially worse than field because Lighthouse throttles to Slow-4G + Moto G Power; real Perfora users (urban India, 4G/5G, mid-range phones) land closer to the field numbers. The lab result is the worst-case and flags what breaks on low-end hardware.
1.3 LCP Phase Breakdown (Mobile, Lighthouse)
LCP element: homepage-banner_mobile.jpg (1800×400, loading="eager" fetchpriority="high" — correctly prioritized).
| Phase | Duration | Note |
|---|---|---|
| Time to First Byte (TTFB) | 80 ms | ✅ Excellent (Cloudflare + Shopify edge) |
| Resource Load Delay | 910 ms | ⚠️ Render-blocking CSS/JS delaying discovery |
| Resource Load Duration | 130 ms | ✅ Fine |
| Element Render Delay | 670 ms | ⚠️ Post-load render work |
| Total LCP | ~6.7 s | TTFB is great; the 1.8s of pre-resource delay (910+670) is the killer |
The LCP is discovered late because render-blocking requests (theme CSS, GoKwik merchant JS, Google Fonts) sit on the critical path. TTFB is 80ms, so this is 100% front-end bloat, not server.
1.4 Performance Issues by Impact
🔴 Critical (lab est. savings >1s)
- Render-blocking requests — est. 990 ms savings.
- Evidence:
custom-css.css(46.4 KiB, 1,440 ms),custom-css-simran.css(6.8 KiB, 640 ms), GoKwikmerchant.integration.js(9.5 KiB, 920 ms), Google Fonts CSS (1.8 KiB, 750 ms). (PSI "Render-blocking requests" insight + URL transfer table.) - Fix: inline critical CSS,
defer/asyncnon-critical theme JS, self-host orpreloadGoogle Fonts withfont-display: swap, load GoKwik after interaction.
- Evidence:
- Main-thread blocking / INP — TBT 2,590 ms.
- Evidence:
theme.js15,410 ms total CPU,clarity-extended.js(scripts.clarity.ms) top forced-reflow 2,500 ms, Freshchat 673 ms main-thread, GoKwik side-cart 735 KiB. Forced reflow 0.8s+. (PSI "Main-thread work" + "Forced reflow" insights.) - Fix: defer Microsoft Clarity + Freshchat + Verifast chatbot init until idle (
requestIdleCallback), remove synchronous reflow loops, code-split theme.js.
- Evidence:
🟡 High (200 ms–1 s)
- Image delivery — est. 1,943 KiB savings. Evidence: hero/product images served at 832×832 (134 KiB) for 395×702 display slots; "Improve image delivery" insight lists 2,335 KiB total with 1,927 KiB savings. Fix: responsive
srcset/AVIF-WebP, right-size hero banner.
- Third-party script bloat. GoKwik (508 KiB, 382 KiB savable), Freshchat (629 KiB), Netcore Smartech (9.7 KiB), farziengineer wallet widget (13.3 KiB), Clarity, Verifast iframe. 7,915 DOM elements (Lighthouse "Diagnostics"). Fix: audit and lazy-init; consolidate.
- Inefficient cache lifetimes — est. 904 KiB. GoKwik assets
None/10mTTL. Fix: set longCache-Controlon static vendor assets (theme/build control limited, but raise Shopify CDN max-age).
🟢 Medium/Low
- >4 preconnect connections (warning in PSI). Preconnects to cdn.shopify.com (×2), pdp.gokwik.co, fonts.googleapis.com — plus preloads. Trim to the 2–3 most critical origins.
- DOM size 7,915 elements (>1,500 warning) — heavy homepage with duplicated marquee/press logos. Lazy-render below-fold sections.
1.5 Resource Transfer Summary (Mobile Lab)
| Category | Transfer | Notable |
|---|---|---|
| 1st-party (Shopify) | ~53 KiB critical CSS/JS + 2.3 MiB images | Images dominate |
| GoKwik | 508 KiB | Checkout/cart SDK — high main-thread cost |
| Freshchat | 629 KiB | Chat widget — lazy-load |
| Netcore / farziengineer / Clarity / Verifast | ~650 KiB combined | Analytics + chatbot iframes |
2. Accessibility Audit
2.1 Critical Issues
- None.
<html lang="en">present,<meta name="viewport">present, 0 images missingaltentirely. Skip-to-content link present.
2.2 High Priority Issues
- 4
<h1>elements on the homepage (logo, section heading, "Explore Oral Care" + a hidden one). WCAG wants a single descriptive H1. Product page has 2 H1s; collection page is cleaner. Fix: one H1 per page (brand/keyword), demote the rest to H2. Evidence:document.querySelectorAll('h1').length= 4 (home), 2 (product).
- 0 ARIA attributes on the homepage (
[aria-]count = 0) despite interactive tabs, carousels, comboboxes, and a chatbot. Tablist/"Shop by Concern" combobox and swiper pagination bullets rely on ARIA that isn't wired. Evidence: PSI "Failing Elements" flags emptyaria-label=""on collection CTA links and tab links. Fix: addaria-labelto icon-only links (e.g. the announcement-bar CTAs, swiper bullets already have labels — add to CTA overlay<a aria-label="">which currently has empty label).
- 73 images with
alt=""on the homepage — many are content images (category tileselectric-toothbrush-category.webp,combos-category.webp, product-group graphicsGroup_25.webp) that are decorative-only because they sit inside linked cards with adjacent visible text. This is acceptable IF the card text is the label, but 30 on the product page (alt=""product thumbnails) should be reviewed — decorative is fine there. Evidence:img[alt=""]= 73 (home), 30 (product).
- Empty
aria-labelon collection banner CTA —<a class="d-block p-absolute ..." aria-label="">wrapping a full-bleed collection link (PSI "Failing Elements"). Fix: add descriptivearia-label("Shop Teeth Whitening").
- Aggregate contrast — Lighthouse a11y = 79 (not 100) implies contrast/label issues on low-contrast text (e.g.
color-lightsubtext on sale prices, announcement bar). Verify the announcement bar and₹strikethrough contrast.
2.3 Positive Findings
- Skip-to-content link ✅, logical heading hierarchy (mostly) ✅, viewport + lang ✅, no missing-alt images ✅, form inputs have labels ✅, keyboard-reachable nav ✅, breadcrumbs on product/blog/collection ✅.
3. SEO Audit
3.1 Technical SEO
| Check | Status | Evidence |
|---|---|---|
| robots.txt | ✅ Comprehensive | Blocks cart/checkout/account, allows catalog; Sitemap: directive present; even Shopify-agentic UCP/MCP documented |
| XML Sitemap | ✅ Present & structured | sitemap.xml → products/pages/collections/blogs sub-sitemaps + sitemap_agentic_discovery.xml |
| Canonical URLs | ✅ Self-referencing | Home, product, collection all self-canonical (verified via DOM) |
| Indexation | ✅ No noindex on key pages | Product/collection/blog all indexable |
| HTTPS | ✅ Enforced | Cloudflare, HSTS present, upgrade-insecure-requests CSP |
| URL structure | ✅ Clean, hyphenated | /products/..., /collections/..., /blogs/... |
| Mobile-friendly | ✅ Responsive | viewport set; 96% mobile audience confirms |
| hreflang | ⚠️ None | No alternate hreflang links (only .atom feed + self). Single-locale (en-IN) site, so not required — see §4 |
3.2 On-Page SEO
- Title tags: ✅ Strong. Home: "Perfora: Clinically Proven Teeth Whitening. High Quality Oral Care – Perfora - Oral Care Solutions" (keyword-led). Product: "Buy Perfora's Automatic Electric Toothbrush Online At Best Prices". Collection: "Teeth Whitening: Get Brighter Teeth At Home!". All ≤60 chars, keyword-near-front.
- Meta descriptions: ✅ Present on home, product, collection, blog. Unique, compelling, keyworded. (This is a common Shopify gap Perfora has avoided.)
- Headings: ⚠️ Multiple H1s (see §2.2).
- OG + Twitter Card: ✅ Complete on home/product/collection/blog (
og:title/description/image/url/type/site_name,twitter:card=summary_large_image). Minor bug:twitter:site=@https://x.com/Perforaofficial— the value should be a handle (@Perforaofficial), not a URL. Fix the theme Liquid variable. - Images: 0 missing-alt (good), but 73 empty-alt (review §2.2). Filenames are descriptive (
homepage-banner_mobile.jpg,electric-toothbrush-category.webp) ✅.
3.3 Schema Markup (JSON-LD)
| Page | Present schema | Gaps |
|---|---|---|
| Home | Organization, WebSite | No BreadcrumbList, no FAQPage, no WebSite+SearchAction (sitelinks search box missed) |
| Product | Organization, Product (+ 2nd Product with AggregateRating 4.55/1168) | No BreadcrumbList on product (visual breadcrumb exists but no schema); brand.name should match Organization name exactly ("Perfora - Oral Care Solutions" vs "Perfora") |
| Collection | Organization, Product (hero only) | No ItemList for the product grid — missed rich-result opportunity; no BreadcrumbList |
| Blog post | Organization, Article (headline, author "Simran Arora", date) | No BreadcrumbList; Article articleBody/image present |
Verified working: Product AggregateRating + reviewCount render star-rich eligibility; Organization sameAs links socials. Note: one JSON-LD block serializes schema.org as http://***schema.org/ in the source — this is a console-redaction artifact, the live block parses fine (AggregateRating confirmed present).
3.4 Internal Linking & Keyword Targeting
- Strong: blog posts link to product collections; homepage "Explore Oral Care" + "Shop by Concern" cross-link; footer quick-links.
- No broken internal collection links observed; no
?variant=pollution on collection pages (0 variant links of 26 product links — PLP audit sibling found the price sort broken, but variant dup-content is clean). - Keyword targeting aligned (whitening/toothbrush/concern pages).
3.5 E-E-A-T Signals
- Experience/Expertise: Founder story, "clinically proven," dentist-formulated copy, author bylines on blog (Simran Arora). ✅
- Authoritativeness: Press logos (BW Disrupt, Elle, Outlook, Times of India) on homepage marquee. ✅
- Trustworthiness: Phone +91 9999289288, email hello@perforacare.com, full policy set (shipping/return/refund/warranty/privacy/terms), loyalty, track-order. ✅ Strong for D2C.
4. International SEO
Not applicable — single locale. The site is en-IN only (CrUX form factors + content-language: en-IN + IN localization cookie). No hreflang is expected or required. No evidence of /fr/, /de/ or other locale prefixes. Shopify's agentic-discovery sitemap is a bonus for AI crawlers, not a locale concern.
5. Best Practices & Security
5.1 Security Headers (from curl -sI)
| Header | Value | Assessment |
|---|---|---|
| Strict-Transport-Security | max-age=7889238 (~91 days) | 🟡 Weak — no includeSubDomains, no preload. Bump to max-age=31536000; includeSubDomains; preload |
| X-Frame-Options | DENY | ✅ |
| X-Content-Type-Options | nosniff | ✅ |
| Content-Security-Policy | block-all-mixed-content; frame-ancestors 'none'; upgrade-insecure-requests | 🟡 Present but no script-src/object-src directive — doesn't mitigate XSS injection; add a script-src allowlist (hard with GoKwik/Shopify inline, but nonce/strict-dynamic feasible) |
| X-XSS-Protection | 1; mode=block | ✅ (legacy, harmless) |
| Referrer-Policy | not set | 🟢 Low — add strict-origin-when-cross-origin |
| Permissions-Policy | not set | 🟢 Low — restrict camera/microphone (Verifast chatbot requests them) |
| COOP/COEP | not set | 🟢 Low |
5.2 Modern Standards
- No
document.write, valid HTML5 doctype, UTF-8 declared, no mixed content (CSP enforces). ✅ - Cloudflare + Shopify managed infra;
x-download-options: noopenpresent. ✅ - Verifast chatbot iframe requests
allow="microphone; camera"— justify or scope down (Privacy/Permissions-Policy gap). ⚠️
6. Content Quality Assessment
6.1 Image Quality & Authenticity
🔴 Brand-risk finding: 4 ChatGPT_Image_* files on the homepage.
ChatGPT_Image_Jul_15_2026_02_51_22_PM.png(used as "Purple Magic Whitening Mouthwash" hero tile)ChatGPT_Image_Jul_15_2026_02_28_27_PM.png(used as "Purple Magic Whitening Toothpaste" hero tile)ChatGPT_Image_Aug_4_2026_04_30_13_PM.png(alt = filename itself — unlabeled, 591×455)ChatGPT_Image_Aug_14_2026_10_49_04_AM.png(used as "Granite Black Power Flosser + Purple Serum" tile)
Two of these carry a product-name alt (so they're standing in for product photography), and one has no alt at all (alt literally equals the filename). For a "clinically proven / design-led" premium brand, AI-generated product imagery on above-the-fold conversion tiles is an authenticity mismatch — customers expect real product shots. Severity: Medium for general e-com, but flagged Critical-to-brand here given Perfora's positioning. Recommendation: replace with real studio product photography; at minimum rename alt text and move AI assets below the fold.
Other image notes: 73 alt="" images are mostly decorative (category icons, press logos, product group graphics) — acceptable. Homepage banner and product images are real photography. No other AI patterns (Gemini_, Picsart, unnamed_) found.
6.2 Trust Signals
Strong: phone/email visible in header + footer, 8 policy pages, loyalty program, "30k customers / 4.77 (6105 reviews)" social proof on hero, press logos, shark-tank badge in meta. ✅
6.3 Breadcrumb Navigation
Visual breadcrumbs present on product, collection, blog (✅). BreadcrumbList schema missing on all (only visual) — add JSON-LD for SERP breadcrumb rich results.
6.4 Review / Social Proof
Judge.me-style ratings render on cards + product pages with AggregateRating schema. ✅ Rich-result eligible.
7. Priority Recommendations
🔴 Immediate (This Week)
| # | Issue | Impact | Effort |
|---|---|---|---|
| 1 | Fix INP (interactivity) — defer Clarity, Freshchat, Verifast, Netcore init via requestIdleCallback; remove forced-reflow loops | Real-user CWV fail → ranking/UX | Med |
| 2 | Inline critical CSS + defer/async theme + GoKwik JS (render-blocking, 990ms savable) | Mobile LCP + FCP | Med |
| 3 | Replace ChatGPT_Image_* hero tiles with real product photography (or move below fold + fix alt) | Brand authenticity / conversion | Low |
🟡 Short-Term (This Month)
| # | Issue | Impact | Effort |
|---|---|---|---|
| 4 | Single H1 per page (home has 4, product has 2) | Heading/SEO clarity | Low |
| 5 | Add BreadcrumbList schema to product/collection/blog | SERP breadcrumb rich results | Low |
| 6 | Add ItemList schema to collection pages | Product carousel rich results | Low |
| 7 | Fix twitter:site value (@https://x.com/... → @Perforaofficial) | Social preview correctness | Low |
| 8 | Add ARIA labels to icon/CTAs with empty aria-label (collection banner, tabs) | A11y (79→90+) | Low |
| 9 | Responsive image srcset/AVIF for hero + product (1,943 KiB savable) | Mobile LCP | Med |
| 10 | Add script-src CSP + includeSubDomains; preload HSTS + Referrer/Permissions-Policy | Security hardening | Low |
🟢 Long-Term (This Quarter)
| # | Issue | Impact | Effort |
|---|---|---|---|
| 11 | Audit & consolidate third-party scripts (GoKwik 508KiB, Freshchat 629KiB, farziengineer, Verifast iframe) | Main-thread/TBT | Med |
| 12 | Reduce DOM to <1,500 (7,915 now) via lazy below-fold sections | Performance | Med |
| 13 | Add WebSite+SearchAction schema (sitelinks search box) | SERP feature | Low |
| 14 | Trim preconnects to 2–3 origins | Perf (low) | Low |
| 15 | Long cache TTL on static vendor assets (GoKwik 904 KiB savable) | Perf | Low |
Summary Score Card
| Category | Score | Grade |
|---|---|---|
| Performance (Mobile) | 31/100 | 🔴 |
| Accessibility | 79/100 | 🟡 |
| Best Practices | 73/100 | 🟡 |
| SEO | 92/100 | 🟢 |
| Content Quality | ~75/100 (AI-image brand risk) | 🟡 |
| Security | ~78/100 (CSP/HSTS gaps) | 🟡 |
| UX / Trust | ~88/100 | 🟢 |
| International SEO | N/A (single locale) | — |
| Overall (mobile-weighted) | ~69/100 | 🟡 |
Sources & Citations
- CrUX field data — https://cruxvis.withgoogle.com/#/ (origin
https://perforacare.com, phone, summary 2026-08-29; weekly LCP/INP/CLS time series Nov 2025–Aug 2026). PSI field panel cross-confirmed (Mobile CWV "Failed" = INP Needs Improvement; LCP 2.3s, CLS 0.05). - Lighthouse lab (Mobile) — https://pagespeed.web.dev/ (report 2026-09-07 08:19 UTC, Lighthouse 13.4.1, Moto G Power / Slow-4G). Scores: Perf 31, A11y 79, BP 73, SEO 92. Metrics FCP 3.3s, LCP 6.7s, TBT 2,590ms, CLS 0.065, SI 13.2s. Desktop lab run did not complete (headless flake).
- Security headers / robots.txt / sitemap —
curl -sI https://perforacare.com/,curl -sL .../robots.txt,curl -sL .../sitemap.xml(+ products/pages/collections/blogs sub-sitemaps). 2026-09-07. - JS-rendered DOM inspection —
browser_consoleon homepage, product (/products/electric-toothbrush-model001), collection (/collections/teeth-whitening-products), blog post (/blogs/gum-health/6-ways-to-whiten-your-teeth-at-home-backed-by-science). Schema types, OG/Twitter, H1 counts, ARIA counts, alt-text audit, AI-image filename scan (4ChatGPT_Image_*hits), variant-link count (0/26). 2026-09-07. - Business context —
business-analysis.md(this workspace): 96.1% phone audience, Shopify+GoKwik stack, ~₹70 Cr FY25, Shark Tank S2.
Caveat: Desktop Lighthouse lab metrics were not captured (the PSI desktop analysis hung in the headless browser). Desktop performance should be re-tested in a standard browser before drawing desktop-specific conclusions; given the 24:1 mobile audience ratio this does not change prioritization.