Website Analysis Example: A Real Audit, Step by Step

Developer reviewing website audit data and performance metrics on a laptop screen with code editor open

A prospect sent me their site last month. "It's slow and nobody buys. Can you look?" The homepage was a 4.2MB React bundle serving a plumbing business in Ohio. Every SEO tool gave them a green score. Conversions were still flat. Here's the actual audit I ran, section by section, so you can copy the method the next time you (or a client) stares at a site that "should be working."

I ran this through BizFlowAI's automated audit first to get the machine-readable pass, then hand-verified everything. Both matter. Tools miss context; humans miss files. I'll show you both layers.

The site and the starting numbers

The site: a 14-page marketing site on Next.js 13, hosted on Vercel, ~1,900 monthly visitors from Google, ~11 form submissions per month. Owner told me the phone rings maybe twice a week. Average session was 41 seconds. Bounce rate 71%.

Before touching anything, I collected four data snapshots:

  • Crawl — Screaming Frog, JS rendering on, 400 URL limit.
  • Search Console — last 90 days, all queries, all pages.
  • Analytics — GA4 events for the last 30 days.
  • Lab performance — PageSpeed Insights on 3 representative URLs (home, service page, blog post).

The BizFlowAI audit ran in parallel and flagged 47 issues across four buckets: technical SEO (18), content (11), speed (9), and conversion (9). I only trust automated audits for the inventory. Prioritization is a human call. A missing meta description on a 404 page isn't the same as a missing H1 on the top-converting service page, and no tool weights that correctly out of the box.

Technical SEO: what the crawl actually revealed

Direct answer: The site had three high-impact technical issues — a broken canonical strategy from Next.js's default routing, indexation of paginated blog pages that split link equity, and a sitemap that listed 47 URLs while the crawler found 112. Everything else was cosmetic.

Here's what I check on every site, in order:

  1. Indexability of money pages. I pull the list of URLs that generate revenue (or would) and check each for noindex, canonical, robots.txt block, and status code. On this site, /services/emergency-repair — the highest-intent page — had a self-referencing canonical to /services/emergency-repair?ref=nav because someone had added a tracking param to the internal nav link. Google saw two URLs; one was canonicalized to a variant that wasn't in the sitemap.

  2. Duplicate content from parameters and pagination. Blog pagination (/blog/page/2, /blog/page/3...) was indexed with unique title tags but identical meta descriptions. That's not catastrophic, but it dilutes the /blog root.

  3. Sitemap vs crawl delta. Any URL in the sitemap that returns anything other than 200, or any 200 URL not in the sitemap — that gap is where indexation problems live.

Here's the exact curl I use for a quick canonical check:

for url in \
  "https://example.com/" \
  "https://example.com/services/emergency-repair" \
  "https://example.com/blog"
do
  echo "=== $url ==="
  curl -sL -A "Mozilla/5.0" "$url" \
    | grep -Eo '<link rel="canonical"[^>]+>|<meta name="robots"[^>]+>'
done

Fix priority for this site:

Issue Impact Effort Do it?
Canonical pointing to param URL High — top service page 20 min Yes, immediately
Paginated blog indexed Low 1 hour No, leave it
Sitemap missing 65 URLs Medium 30 min Yes
Missing og:image on 8 pages Low 45 min Later

The tool flagged all four. The tool weighted them roughly equally. That's the gap.

Content: matching pages to real search intent

Direct answer: Two of the four service pages ranked for informational queries ("how to fix a leaking pipe") but were written as transactional pages ("call us now"). Google was sending readers looking for a how-to guide to a page that only sold a service. Bounce rate on those pages was 84%.

I pulled the Search Console queries for each ranking page and grouped them by intent:

  • Informational — "how to", "why does", "what is", "signs of"
  • Commercial investigation — "best", "vs", "cost of", "near me reviews"
  • Transactional — "hire", "emergency", "24 hour", "quote"

The service page for /services/pipe-repair was ranking position 8-14 for "how much does pipe repair cost" and "signs of a burst pipe" — 340 impressions/month combined, 4 clicks. The page had no cost info and no diagnostic content. It had a phone number, three trust badges, and a form.

The fix isn't to gut the transactional page. It's to build the missing informational content and internally link. I mapped it out:

/services/pipe-repair              (transactional — keep as-is)
├── /guides/burst-pipe-signs       (new — informational)
├── /guides/pipe-repair-cost       (new — commercial)
└── /guides/pipe-vs-repipe         (new — commercial investigation)

Each guide gets an unmissable in-context CTA to the service page. This is the "hub and spoke" pattern, and it's boring, and it works. The BizFlowAI audit exports the intent classification as a CSV so you can hand it to a writer without re-doing the analysis. That saved me maybe two hours on this one.

One thing tools cannot do: read a page and tell you whether it answers the query with authority. On the "signs of a burst pipe" guide the client eventually shipped, the difference between a version that ranks and a version that doesn't is a paragraph written by someone who has actually seen a burst pipe at 2am. Ship experience or don't ship the guide.

Speed: what the 4.2MB bundle was actually doing

Direct answer: The homepage shipped 4.2MB of JavaScript for a static marketing page. 2.9MB of that was a full icon library imported as import * as Icons from 'react-icons' when the site used 6 icons. LCP was 4.8s on mobile. Fixing the import dropped the bundle to 480KB and LCP to 1.9s.

The full breakdown from the Chrome DevTools Coverage tab:

Asset type Size Unused % Verdict
Main JS bundle 4.2 MB 78% Tree-shake
Google Fonts 340 KB 60% Subset + preload
Hero image (PNG) 1.1 MB Convert to WebP
Third-party (chat widget) 890 KB Lazy-load
Analytics 92 KB Keep, defer

The single most impactful change was fixing the icon import:

// Before — pulls the entire library
import * as Icons from 'react-icons/fa';
<Icons.FaPhone />

// After — imports only what's used
import { FaPhone } from 'react-icons/fa';
<FaPhone />

Second-biggest win: the chat widget. It loaded synchronously on every page, including at 3am when no support agent was awake. I moved it to load after user interaction:

// Load chat widget only after first user interaction
let chatLoaded = false;
const loadChat = () => {
  if (chatLoaded) return;
  chatLoaded = true;
  const s = document.createElement('script');
  s.src = 'https://widget.example.com/loader.js';
  s.async = true;
  document.body.appendChild(s);
};
['mousemove', 'scroll', 'touchstart'].forEach(evt =>
  window.addEventListener(evt, loadChat, { once: true, passive: true })
);

For images, I stopped fighting Next.js and used next/image with priority on the hero and loading="lazy" on everything below the fold. Google's Core Web Vitals thresholds are the target: LCP under 2.5s, INP under 200ms, CLS under 0.1. All three moved into the green after these three changes.

One caveat on speed audits: PageSpeed Insights runs on a throttled connection and a mid-tier phone. Your Vercel dashboard's Real User Monitoring will show different numbers because your actual users are on faster devices. Both are true. I optimize for the lab score because that's what Google's ranking signal uses, but I report the field data to the client because that's what their customers experience.

Conversion: where the visitors were quietly leaving

Direct answer: The form had 9 fields on mobile, no autofill hints, and the submit button used the site's brand color (a muted teal) that read as "disabled" to a third of users I watched in session recordings. Reducing to 4 fields and changing the button to high-contrast orange lifted form starts by 44% in the next 30 days.

I don't trust conversion audits without watching real sessions. Hotjar, Microsoft Clarity, or Vercel's built-in — pick one, watch 20 sessions, and take notes. The audit tool flagged the form as "too many fields" but couldn't tell me the button looked disabled. A human watching sessions figured that out in eight minutes.

Here's the conversion issue map I built:

Page Issue Evidence Fix
Home Hero CTA below the fold on iPhone SE 22% of mobile traffic on small screens Reduce hero image height by 40%
Home Phone number not a tel: link 3 tap attempts per session on average <a href="tel:...">
Service pages Form 9 fields, only 3 required Session recordings: 6 abandons out of 20 starts 4 fields, autocomplete attributes
Service pages Submit button low contrast Users hovered without clicking Change to #EA580C
Blog posts No CTA at end of article 100% of blog readers left Add related-service card

The autocomplete change is a two-line fix everyone forgets:

<input type="tel" name="phone"
       autocomplete="tel"
       inputmode="numeric"
       placeholder="Phone">
<input type="email" name="email"
       autocomplete="email"
       inputmode="email"
       placeholder="Email">

On iOS, this pulls contact info from the keychain. It shaves 15-30 seconds off the form and the drop-off graph shows it clearly.

How BizFlowAI approaches this

The audit I described is what BizFlowAI runs as a first pass for every client engagement. It crawls the site, pulls Search Console and GA4 data, runs Lighthouse against representative URLs, classifies queries by intent, and outputs a prioritized issue list with a suggested fix for each. What the tool doesn't do is decide which fixes matter for your business — that's the conversation we have with the client after the report lands.

We built it because we kept running the same fifteen checks by hand on every project and realized the boring 80% of an audit is a solved problem. The interesting 20% — reading session recordings, judging content authority, deciding whether to kill or fix a page — is where a human still earns their keep. If you want to see what the automated pass looks like on your own site, the audit report is what to ask for.

What actually shipped, and what the numbers did

The client approved a fixed-scope engagement covering: canonical fix, sitemap regeneration, three new guide pages, bundle optimization, image conversion, form redesign, and button contrast. Total: about 22 hours of work over three weeks.

Results at the 45-day mark (their reporting, I verified in GA4):

  • Organic sessions: up ~35%
  • Form submissions: 11/month → 19/month
  • Phone calls (tracked via tel: clicks): 8/month → 21/month
  • LCP mobile: 4.8s → 1.9s
  • Bounce rate on service pages: 84% → 61%

I'm sharing these because they're honest, not because they'll match yours. Three factors made this site respond quickly: it had existing rankings to build on, the technical fixes were high-leverage, and the client actually shipped the content. Sites without that starting position take longer, and I've had audits where the biggest recommendation was "stop publishing and go get your first ten customers instead."

The checklist to run this yourself

If you're auditing your own site or a client's, run it in this order — the order matters because early findings change how you read later ones:

  1. Crawl the site with JS rendering on. Note total URLs.
  2. Compare to sitemap and Search Console's indexed pages. Every gap is a story.
  3. Pull top 20 pages by clicks and top 20 by impressions. These are your money pages.
  4. Check canonical, robots, and status code for each money page.
  5. Classify ranking queries by intent for each money page. Mismatch = new content opportunity.
  6. Run Lighthouse on 3 representative URLs. Look at unused JS coverage.
  7. Watch 20 session recordings on your highest-traffic conversion page.
  8. Map every issue to impact and effort, then cut anything that isn't high-impact.
  9. Ship in this order: technical fixes → speed → conversion → content. Content takes longest to compound, so start it early but don't wait for it.

Skip step 7 and you'll ship a technically perfect site that still doesn't convert. Skip step 5 and you'll write beautiful content that answers questions nobody asked. The whole point of doing this in order is that each step tells you what to skip in the next one.


Work with BizFlowAI

If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.

Book a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.

More guides like this on the BizFlowAI blog.

Frequently asked questions

How do you audit a slow website that isn't converting?

Start by collecting four data snapshots: a full crawl (Screaming Frog with JS rendering), Search Console query and page data for 90 days, GA4 event data for 30 days, and PageSpeed Insights results for representative URLs. Then audit in four buckets: technical SEO, content-to-intent match, page speed, and conversion. Use automated tools only for inventory, and manually prioritize based on which pages actually drive revenue. Watch 20 real session recordings before making conversion decisions.

Why is my Next.js bundle so large and how do I fix it?

The most common cause is namespace imports from icon or utility libraries, such as `import * as Icons from 'react-icons/fa'`, which pulls the entire library instead of tree-shaking. Switch to named imports like `import { FaPhone } from 'react-icons/fa'` to import only what you use. Also lazy-load third-party widgets (chat, support) after the first user interaction, and use `next/image` with `priority` on the hero and lazy loading below the fold. These three changes commonly cut bundles by 80% or more.

What's the difference between transactional and informational search intent in SEO?

Informational queries use phrases like 'how to,' 'why does,' or 'signs of' — the user wants to learn. Commercial investigation queries use 'best,' 'vs,' or 'cost of' — the user is comparing. Transactional queries use 'hire,' 'emergency,' or '24 hour' — the user is ready to buy. If a service page ranks for informational queries, build separate guides for that intent and internally link them to the transactional page using a hub-and-spoke structure.

How many fields should a lead form have on mobile?

Aim for 3 to 5 fields on mobile. Nine fields is too many and causes drop-off, especially without autofill hints (`autocomplete` attributes) and clear visual hierarchy. Also make sure the submit button uses a high-contrast color that doesn't read as disabled — muted brand colors like soft teals often look inactive to users. Reducing a form from 9 to 4 fields and using a high-contrast button can lift form starts by 40% or more.

Should I trust PageSpeed Insights or Real User Monitoring data?

Both, for different reasons. PageSpeed Insights uses a throttled connection and mid-tier phone, matching what Google uses as a ranking signal — optimize to those Core Web Vitals thresholds (LCP under 2.5s, INP under 200ms, CLS under 0.1). Real User Monitoring from Vercel or similar shows what your actual users experience on their real devices. Report field data to clients but optimize against lab scores for SEO purposes.