Skill: leooooooow/mobile-ux-audit (version 1.1.0)

--- name: mobile-ux-audit description: Audit the mobile shopping experience of an ecommerce store for friction points including page load speed, thumb-reach interactions, form length, checkout flow, and pay-method breadth. Use when mobile conversion rate is lagging desktop, before a major redesign, or quarterly as a hygiene pass. --- # Mobile UX Audit Mobile is usually 65–80% of ecommerce traffic and ~50% of revenue. The gap between traffic share and revenue share is the audit's job: find the thumb-reach errors, the slow hero images, the checkout fields that kill the sale. ## Quick Reference | Decision | Strong | Acceptable | Weak | |---|---|---|---| | LCP (Largest Contentful Paint) | ≤2.0s on 4G | 2.0–2.5s | >2.5s | | INP (Interaction to Next Paint) | ≤150ms | 150–300ms | >300ms | | CLS (Cumulative Layout Shift) | ≤0.05 | ≤0.1 | >0.1 | | Tap targets | ≥44×44pt with ≥8pt spacing | 40pt with tight spacing | <40pt, close together | | Checkout fields | ≤8 fields, one-page | 10–12 fields, 2 pages | 15+ fields, 3+ pages | | Pay methods | Apple Pay, Google Pay, card, 1 local | Card + PayPal | Card only | | Guest checkout | Default, no account required | Account optional after checkout | Forced account creation | ## Problems this skill solves 1. **Conversion rate 40% lower on mobile than desktop** with no clear diagnosis. 2. **Cart abandonment spiking at the address-entry step** — usually a mobile-keyboard/autofill problem. 3. **PDP hero image taking 4+ seconds to load** because the team uses the same 3000px-wide asset as desktop. 4. **Checkout buttons in the top third of the screen** requiring an awkward thumb stretch. 5. **Apple Pay / Google Pay not enabled** on a store where 70% of users are on iOS or Android. 6. **Modals and popups that cover the close button** on small screens. 7. **Tap targets smaller than the thumb pad**, producing fat-finger errors on filters and quantity steppers. ## Workflow ### Step 1 — Measure Core Web Vitals in the field Pull the last 28 days of real-user metrics from PageSpeed Insights (CrUX), Google Search Console, or your RUM tool (Datadog, New Relic, Sentry, or Shopify's built-in). Record p75 LCP, INP, CLS for mobile. Compare to the Quick Reference table. Lab-test tools (Lighthouse) give consistent scores but do not reflect real users — always lead with field data. ### Step 2 — Walk the funnel on a real device Not an emulator, not Chrome DevTools device mode. Use an actual iPhone and an actual mid-range Android (Pixel 6a or similar — not the latest flagship). Walk: home → category → PDP → add to cart → cart → checkout → payment. Note every friction: slow load, mis-sized tap target, layout shift, confusing state, keyboard-covers-field moment. ### Step 3 — Audit thumb reach The comfortable thumb zone on a 6-inch phone is the bottom two-thirds of the screen. Anything in the top third (headers, close buttons, primary CTAs) requires a reach or a hand shift. Map every primary CTA on the funnel and flag anything above the middle. ### Step 4 — Audit form fields List every field in the checkout. Score each: required or optional, keyboard type (email, tel, numeric), autocomplete attribute, inline validation. Target ≤8 required fields total. Common kill-fields: "confirm password," "phone number for delivery updates," "how did you hear about us." ### Step 5 — Audit the payment step List enabled pay methods. For every market the store serves: - Apple Pay enabled with domain verification? Required for iOS conversion. - Google Pay enabled? Required for Android conversion. - One local method per region (iDEAL in NL, Bancontact in BE, Klarna / Afterpay for installments, SEPA in EU, Pix in BR, UPI in IN). - Card fields with proper keyboard (numeric, cardtype icons, CVV as numeric). - 3DS flow is not full-page redirect (use inline 3DS). ### Step 6 — Image and asset audit - Hero images: served as WebP or AVIF, responsive srcset, ≤200KB at mobile breakpoint. - Below-fold images: lazy-loaded. - Fonts: WOFF2, subset to used characters, preloaded for critical text. - No layout shift from image or ad loads (`width` and `height` attributes or aspect-ratio boxes). - Video: don't autoplay. If used, poster image first, lazy-load the `<video>` element. ### Step 7 — Document findings with priority Produce a ranked list: P0 (blocks checkout), P1 (measurably hurts conversion), P2 (polish). Each item gets the friction described, the screen(s) affected, and a concrete fix. ## Example 1 — Shopify store, 62% mobile traffic, 28% mobile conversion rate vs. desktop Findings from a 2-hour audit: - **P0**: Apple Pay not enabled despite 58% of mobile users on iOS. Domain unverified in Apple Pay portal. Estimated impact: +8–12% mobile checkout completion. - **P0**: Checkout has 14 fields including optional company name, phone "for delivery," and a captcha that fails 30% of the time on mobile. Impact: +5–8% checkout completion from field reduction. - **P1**: Hero image is a 4000px JPEG at 1.2MB. Re-export at 1200px WebP (~120KB). LCP drops from 3.8s to 1.9s. - **P1**: Add-to-cart button top-right of PDP on mobile, requiring thumb reach. Move to sticky-bottom. - **P1**: Filter modal on category page covers the close-X behind the OS status bar on iPhone. Add 44pt top padding. - **P2**: "Suggested for you" section loads below the hero with a 300ms layout shift (CLS 0.18). Reserve space. - **P2**: Login prompt appears after 15 seconds on every page. Reduce to once-per-session. Estimated combined lift: 20–30% on mobile conversion over 4–6 weeks after deployment. ## Example 2 — Headless store (Next.js + commerce API), strong desktop, poor mobile INP The team already optimizes LCP and CLS and has green Core Web Vitals on desktop. Mobile INP is 420ms — users tap and nothing happens for nearly half a second. - **P0**: Main-thread blocked by an analytics bundle firing synchronously on every route change. Move to a web worker or defer 2 seconds after route settle. Expected INP drop: 420ms → 180ms. - **P0**: The "add to cart" handler calls three tracking scripts synchronously before showing the cart drawer. Fire tracking async, show drawer immediately. Expected: drawer opens in <100ms instead of 600ms. - **P1**: Image carousel on PDP uses a heavy library (40KB) that blocks interaction. Swap for CSS-scroll-snap approach, 2KB, same UX. - **P1**: Variant selector re-renders the entire PDP on each change. Memoize properly or split into a sibling component. - **P2**: Service worker caches stale HTML for 24h, so bug fixes don't reach users fast. Reduce TTL to 1h and add a "fresh version available" toast. Strong teams still have mobile-INP debt. The fix is usually "less JavaScript on tap," not "smaller hero image." ## Common mistakes 1. **Auditing only on the latest iPhone.** A mid-range Android at 4G is the real median user. 2. **Using Lighthouse as the only signal.** Lab scores miss cold-start jank and main-thread contention. 3. **Treating mobile as "desktop minus width."** The thumb pattern, keyboard behavior, and attention span are fundamentally different. 4. **Fixing LCP with a CDN and declaring victory.** LCP is three factors: server response, render-blocking resources, and hero-asset size. The CDN only touches one. 5. **Forcing account creation before checkout.** This is a 20%+ conversion hit on cold traffic. 6. **Modals with no visible close button on 4-inch screens.** Test on a small device; buttons crop out. 7. **Infinite-scroll product listing without pagination cues.** Users feel lost and leave. 8. **Autoplay video on mobile.** Eats data, battery, and autoplay policies often block it anyway. 9. **Sticky headers that eat 20% of vertical real estate.** On a phone, every pixel counts. 10. **Not testing with JavaScript disabled.** Many mobile users have flaky JS loading; a site that only works with full JS is broken for them. ## Resources - `references/output-template.md` — Audit report template with P0/P1/P2 structure. - `references/core-web-vitals.md` — How to measure and interpret LCP, INP, CLS in the field. - `references/checkout-checklist.md` — Mobile checkout audit checklist with field-by-field notes. - `references/thumb-zones.md` — Thumb-reach diagrams and interaction patterns. - `assets/mobile-audit-checklist.md` — Full pre-publish audit checklist.

path: references/output-template.md
content: # Mobile UX Audit Report — Template

Use this format for audit deliverables. One document per audit, shared with the product and engineering teams.

## Executive summary

- **Store / property**: [name]
- **Date**: [YYYY-MM-DD]
- **Auditor**: [name]
- **Devices tested**: [iPhone XX, Pixel Xx, etc.]
- **Networks tested**: [Wi-Fi, 4G, 3G-throttled]

**Headline metrics (p75, last 28 days):**

- LCP: [Xs] — target ≤2.0s
- INP: [Xms] — target ≤150ms
- CLS: [X] — target ≤0.05
- Mobile conversion rate: [X%] vs. desktop [Y%]
- Mobile cart abandonment: [X%]

**Top-3 fixes**, in priority order:

1. [P0 fix] — estimated impact: [X% lift]
2. [P0 fix] — estimated impact: [X% lift]
3. [P1 fix] — estimated impact: [X% lift]

## Findings by priority

### P0 — blocks or significantly degrades checkout

For each finding, include:

- **Finding**: [one sentence description]
- **Screen / step**: [home / PDP / cart / checkout / payment]
- **Evidence**: [screenshot, metric, session recording ID]
- **Fix**: [concrete implementation]
- **Owner**: [team / role]
- **Estimated impact**: [X% lift, Y ms improvement]

Repeat per P0 finding.

### P1 — measurable conversion or engagement impact

Same structure as P0.

### P2 — polish and hygiene

Same structure as P0 and P1.

## Funnel walkthrough notes

Step-by-step notes from the in-device walk. Helpful for reviewers who didn't do the audit. Optional but valuable for the first audit of a store.

- **Home → category**: [notes]
- **Category → PDP**: [notes]
- **PDP → cart**: [notes]
- **Cart → checkout**: [notes]
- **Checkout → payment**: [notes]
- **Payment → confirmation**: [notes]

## Benchmarks and context

- Industry p75 mobile LCP for the store's category: [X s]
- Competitor mobile CVR estimate: [X%]
- Last audit date and change since: [delta]

## Appendix: raw data

- PageSpeed Insights link
- Search Console Core Web Vitals screenshot
- Session recording replays (list IDs, timestamps)
- Device spec list used

## Next review

Suggested next audit: [YYYY-MM-DD] (quarterly by default; sooner if a major launch lands).


path: references/core-web-vitals.md
content: # Core Web Vitals — Practical Guide

Core Web Vitals are three metrics Google uses to score user experience. They correlate strongly with conversion on ecommerce sites.

## The three metrics

### LCP — Largest Contentful Paint

Time from navigation start to the render of the largest visible content element (usually the hero image or H1).

- **Good**: ≤2.0s
- **Needs improvement**: 2.0–2.5s
- **Poor**: >2.5s

Common causes of poor LCP:

- Hero image too large or served at desktop resolution on mobile.
- Slow server response (TTFB >600ms).
- Render-blocking CSS or JS.
- Font loading delay for the text that is the LCP element.

### INP — Interaction to Next Paint

Time from user interaction (tap, click, key press) to the next frame that reflects the result. Replaced FID in 2024.

- **Good**: ≤150ms
- **Needs improvement**: 150–300ms
- **Poor**: >300ms

Common causes of poor INP:

- Heavy JavaScript on interaction (tracking calls, re-renders).
- Long tasks blocking the main thread.
- Synchronous handlers that should be async.
- Third-party scripts doing work on every interaction.

### CLS — Cumulative Layout Shift

Sum of unexpected layout shifts during the page's lifetime. A tap moving because an ad loaded is a bad CLS event.

- **Good**: ≤0.05
- **Needs improvement**: ≤0.1
- **Poor**: >0.1

Common causes of poor CLS:

- Images without width/height attributes.
- Ads or embeds inserted without reserved space.
- Fonts that reflow text (use `font-display: optional` or preload).
- Dynamically injected content above existing content.

## Field data vs. lab data

**Field data** (CrUX, RUM): real users, varied devices and networks. This is what Google uses for ranking and what reflects real conversion.

**Lab data** (Lighthouse, WebPageTest): consistent hardware and network. Good for catching regressions in CI; do not use as your only signal.

Always lead with field data. Lab data is a proxy.

## How to get field data

### For a public site

- **PageSpeed Insights**: enter your URL, see CrUX data if your site has enough traffic.
- **Google Search Console**: Core Web Vitals report with URL groups.
- **CrUX API / CrUX Dashboard**: historical trends by country.

### For your own users

- **web-vitals library** (by Google): tiny JS, reports to your analytics.
- **Datadog RUM**, **New Relic Browser**, **Sentry Performance**: paid RUM services.
- **Shopify Web Performance** dashboard for Shopify stores.
- **Vercel Analytics** for Vercel-hosted Next.js apps.

## How to improve LCP

1. Identify the LCP element in DevTools Performance tab.
2. If it's an image: serve a properly sized WebP/AVIF with `fetchpriority="high"` and preload.
3. If it's text: preload the font, use `font-display: optional`.
4. Reduce server response time (TTFB target <600ms).
5. Minimize render-blocking CSS; inline critical CSS for above-fold content.
6. Defer non-critical JavaScript.

## How to improve INP

1. Identify slow interactions with the INP dev tool or `event-timing` API.
2. Break long tasks with `setTimeout(fn, 0)`, `scheduler.yield()`, or `requestIdleCallback`.
3. Move heavy work to a web worker.
4. Audit third-party scripts — defer, async, or remove.
5. Reduce React re-renders (memoization, virtualization for long lists).
6. Show feedback (loading state) immediately on tap; do real work asynchronously.

## How to improve CLS

1. Add `width` and `height` attributes to every image.
2. Reserve space for ads, embeds, and dynamically inserted components.
3. Preload critical fonts to prevent FOUT reflow.
4. Use CSS transforms for animations (not layout-triggering properties).
5. Avoid inserting content above existing content unless user-initiated.

## Setting realistic targets

- For a greenfield headless build: green on all three is achievable within the first quarter of launch.
- For an older Shopify or Magento store: LCP and CLS are usually fixable in weeks; INP takes months because JavaScript debt accumulated over years.
- The biggest conversion wins come from moving from "Poor" to "Needs improvement" on any metric — not from "Needs improvement" to "Good."


path: references/checkout-checklist.md
content: # Mobile Checkout Audit Checklist

The checkout is where audit findings turn into revenue lift. Walk the flow field-by-field on a real mobile device.

## Pre-checkout (cart page)

- [ ] Cart has sticky bottom "Checkout" button on mobile
- [ ] Line items show image, title, size/variant, quantity, price
- [ ] Quantity stepper has ≥44×44pt buttons with ≥8pt spacing
- [ ] Item removal requires only 1 tap with confirmation
- [ ] Promo code field is hidden by default (collapsible) — otherwise every user hunts for one
- [ ] Shipping estimate visible before starting checkout
- [ ] Tax estimate visible for markets that include tax in price

## Checkout entry

- [ ] Guest checkout is the default; account creation is optional at the end
- [ ] Sign-in link is subtle, not prominent (defaults to guest)
- [ ] Express pay buttons visible first: Apple Pay, Google Pay, Shop Pay / PayPal
- [ ] Express pay buttons have correct height and spacing, native-feeling

## Contact information

- [ ] Email field uses `type="email"` for correct keyboard
- [ ] Email field has `autocomplete="email"`
- [ ] SMS / marketing opt-in is a checkbox, unchecked by default
- [ ] Phone number is optional (or clearly required with reason)

## Shipping address

- [ ] Country selector at the top so subsequent fields format correctly
- [ ] Address autocomplete (Google Places, Loqate, etc.) reduces typing
- [ ] `autocomplete` attributes on every field (`street-address`, `address-level2` for city, `postal-code`, `country`)
- [ ] ZIP/Postal field uses numeric keyboard where appropriate
- [ ] State/Province is a dropdown or autocomplete, not free text
- [ ] Address line 2 is optional and labeled as such

## Shipping method

- [ ] Options clearly labeled with price and delivery window
- [ ] Default selection is a reasonable middle option, not the most expensive
- [ ] Free-shipping threshold progress shown if applicable

## Payment

- [ ] Card number field uses `inputmode="numeric"` and `autocomplete="cc-number"`
- [ ] Card icons shown next to the field or inline as user types
- [ ] Expiry field uses `inputmode="numeric"` with auto-formatting (MM/YY)
- [ ] CVV uses `inputmode="numeric"` with appropriate length
- [ ] Billing address defaults to shipping address
- [ ] 3DS flow is inline, not a full-page redirect
- [ ] Apple Pay / Google Pay alternative visible as a fallback path

## Review and place order

- [ ] Order summary always visible (collapsible on mobile)
- [ ] Total, subtotal, shipping, tax clearly broken out
- [ ] Terms and conditions link is reachable without leaving checkout
- [ ] "Place order" button is sticky-bottom or clearly dominant
- [ ] After tapping "Place order," button shows loading state to prevent double-tap

## Confirmation page

- [ ] Order number and summary visible immediately
- [ ] Clear expectation of next steps (email confirmation, shipping time)
- [ ] Account creation offered post-checkout as a one-tap option
- [ ] Social share or referral offered (optional, post-sale)

## Performance

- [ ] Checkout pages load in ≤2s on 4G
- [ ] Transitions between steps feel immediate (no full-page reload on SPA)
- [ ] Validation errors appear inline, not at the top of the page
- [ ] Error messages are specific and helpful ("ZIP code doesn't match state" not "Invalid address")

## Accessibility

- [ ] All form labels are associated with inputs (`<label for=...>` or wrapping)
- [ ] Error state announced to screen readers (`aria-live`)
- [ ] Focus visible when tabbing through fields
- [ ] Color contrast ≥4.5:1 for all text
- [ ] Tap targets never smaller than 44×44pt


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)