<?php include 'header.php'; ?>

<body>

  <div class="nav-bg" data-noprint>
    <div class="wrap nav">
      <a href="index.html" class="brand"><span class="brand-mark"><i></i></span><span
          class="brand-name">Crawlie</span></a>
      <div class="nav-links" data-nav-links>
        <a class="nav-link" href="index.html">Home</a>
        <a class="nav-link" href="tools.html">Free tools</a>
        <a class="nav-link mobile-only" href="index.html#audit">Site audit</a>
        <a class="nav-link" href="blog/index.html">Blog</a>
        <a class="nav-link" href="about.html">About</a>
        <a class="nav-link" href="contact.html">Contact</a>
        <a class="btn-ghost" href="index.html#audit">New audit</a>
      </div>
      <button class="nav-toggle" data-nav-toggle aria-label="Menu"><span></span></button>
    </div>
  </div>

  <div class="page-with-sidebar">
    <div class="page-main">
      <div class="wrap-mid" style="padding-top:34px;padding-bottom:100px;" data-report>

        <!-- ===== ENTRY / URL BAR (always visible so people can re-run) ===== -->
        <form id="audit-bar" data-noprint
          style="display:flex;align-items:center;gap:8px;background:#fff;border:1.5px solid var(--border-strong);border-radius:999px;padding:8px 8px 8px 22px;max-width:640px;margin:0 auto 30px;box-shadow:var(--shadow-card);">
          <span class="mono" style="color:var(--faint);font-size:15px;">https://</span>
          <input id="audit-url-input" class="mono" placeholder="yourwebsite.com"
            style="flex:1;border:none;outline:none;font-size:15px;color:var(--ink);background:transparent;min-width:0;"
            autocomplete="off">
          <button type="submit" class="btn btn-primary btn-md">Run audit</button>
        </form>

        <!-- ===== SCANNING STATE ===== -->
        <div id="state-scanning" class="hidden" data-noprint>
          <div class="card center" style="max-width:520px;margin:40px auto;padding:50px 36px;">
            <div
              style="width:56px;height:56px;border-radius:50%;border:4px solid var(--violet-100);border-top-color:var(--violet-600);margin:0 auto 24px;animation:spin 0.9s linear infinite;">
            </div>
            <div style="font-weight:700;font-size:17px;margin-bottom:8px;" id="scan-status">Fetching your page...</div>
            <div class="muted" style="font-size:13.5px;margin-bottom:22px;" id="scan-target">—</div>
            <div style="height:8px;background:var(--violet-100);border-radius:999px;overflow:hidden;">
              <div
                style="height:100%;background:linear-gradient(90deg,#7c5cff,#5a32f0);border-radius:999px;animation:scanfill 3.2s ease forwards;">
              </div>
            </div>
          </div>
        </div>

        <!-- ===== FETCH FAILED / PASTE FALLBACK ===== -->
        <div id="state-fallback" class="hidden" data-noprint>
          <div class="card" style="max-width:640px;margin:20px auto;padding:34px;">
            <div class="badge badge-warning" style="margin-bottom:14px;">Couldn't fetch automatically</div>
            <h2 style="font-size:22px;margin-bottom:10px;">We couldn't load that page directly</h2>
            <p class="muted" style="font-size:14.5px;line-height:1.6;margin-bottom:18px;" id="fallback-reason">Some
              sites block cross-origin requests from browser-based tools.</p>
            <p class="muted" style="font-size:14.5px;line-height:1.6;margin-bottom:10px;">Paste the page's HTML source
              instead — right-click the page → <strong>View Page Source</strong> → copy all → paste below — and we'll
              analyze it locally in your browser.</p>
            <div class="field">
              <textarea id="fallback-html" class="textarea" rows="8"
                placeholder="<html>...paste full page source here...</html>"></textarea>
            </div>
            <div class="flex gap-10" style="flex-wrap:wrap;margin-bottom:22px;">
              <button class="btn btn-primary btn-md" id="fallback-analyze">Analyze pasted HTML</button>
              <button class="btn btn-outline btn-md" id="fallback-retry">Try fetching again</button>
            </div>

            <details style="border-top:1px solid var(--border);padding-top:16px;">
              <summary style="cursor:pointer;font-weight:700;font-size:13.5px;color:var(--violet-700);">Using your own
                fetch backend? (fixes stubborn sites)</summary>
              <p class="muted" style="font-size:13px;line-height:1.6;margin:12px 0;">Some sites block every public
                relay. Deploy one of the backends in this download's <code class="mono">backend/</code> folder
                (Cloudflare Worker, Vercel, or PHP+MySQL — see <code class="mono">backend/README.md</code>), then paste
                its URL here — it's saved locally in your browser and tried first on every future scan.</p>
              <div class="flex gap-10" style="flex-wrap:wrap;">
                <input id="backend-url-input" class="input mono" placeholder="https://your-worker.example.workers.dev"
                  style="flex:1;min-width:220px;">
                <button class="btn btn-outline btn-sm" id="backend-url-save">Save</button>
                <button class="btn btn-outline btn-sm" id="backend-url-clear">Clear</button>
              </div>
              <p class="hint" id="backend-url-status" style="margin-top:8px;"></p>
            </details>
          </div>
        </div>

        <!-- ===== RESULTS ===== -->
        <div id="state-results" class="hidden">

          <div class="flex justify-between items-center" style="flex-wrap:wrap;gap:14px;margin-bottom:26px;"
            data-noprint>
            <div>
              <div class="eyebrow" style="margin-bottom:4px;">SEO audit report</div>
              <div class="mono" id="result-url" style="font-size:15px;font-weight:700;"></div>
              <div class="muted" style="font-size:12.5px;margin-top:2px;" id="result-date"></div>
            </div>
            <div class="flex gap-10" style="flex-wrap:wrap;">
              <button class="btn btn-outline btn-md" id="btn-print">Print</button>
              <button class="btn btn-soft btn-md" id="btn-download-html">Download HTML</button>
              <button class="btn btn-primary btn-md" id="btn-download-pdf">Download PDF report</button>
            </div>
          </div>

          <!-- score summary -->
          <div class="card" style="padding:30px;margin-bottom:22px;">
            <div class="score-summary-grid">
              <div style="display:grid;place-items:center;">
                <div class="donut" id="score-donut">
                  <div class="donut-inner">
                    <div>
                      <div class="donut-score" id="score-number">&ndash;</div>
                      <div class="donut-label" id="score-grade-label">SEO score</div>
                    </div>
                  </div>
                </div>
              </div>
              <div class="flex-col gap-14" id="category-bars"></div>
            </div>
          </div>

          <div class="result-split" style="margin-bottom:22px;">
            <div class="card" style="padding:26px 28px;">
              <div class="flex justify-between items-center" style="margin-bottom:18px;">
                <div style="font-weight:800;font-size:18px;">Fix these first</div>
                <span class="muted" style="font-size:13px;font-weight:600;" id="issue-count">—</span>
              </div>
              <div class="flex-col gap-10" id="issues-list"></div>
            </div>

            <div class="card" style="padding:26px 28px;">
              <div style="font-weight:800;font-size:18px;margin-bottom:5px;">Key metrics</div>
              <div class="muted" style="font-size:13px;margin-bottom:20px;">What we measured on this page</div>
              <div class="flex-col gap-10" id="metrics-list" style="font-size:13.5px;"></div>
            </div>
          </div>

          <div class="card" style="padding:26px 28px;margin-bottom:22px;" data-noprint>
            <div style="font-weight:800;font-size:18px;margin-bottom:14px;">Meta preview</div>
            <div style="border:1px solid var(--border);border-radius:14px;padding:16px 18px;max-width:560px;">
              <div style="color:#1a0dab;font-size:18px;line-height:1.3;margin-bottom:3px;" id="preview-title">—</div>
              <div class="mono" style="color:#006621;font-size:13px;margin-bottom:5px;" id="preview-url">—</div>
              <div class="muted" style="font-size:13.5px;line-height:1.5;" id="preview-desc">—</div>
            </div>
          </div>

          <div class="center" style="margin-top:34px;" data-noprint>
            <p class="muted" style="font-size:13.5px;">Want to see how you stack up? <a
                href="tools/competitor-comparison.html"
                style="color:var(--violet-700);font-weight:700;text-decoration:none;">Run a competitor comparison →</a>
            </p>
          </div>
        </div>

      </div>
    </div>
    <aside class="tools-sidebar" data-noprint><input type="text" class="sidebar-search" id="sidebar-search-input"
        placeholder="Find a tool..." aria-label="Search tools">
      <details class="sidebar-cat" open>
        <summary><span class="sidebar-cat-dot" style="background:var(--violet-600);"></span>Audits &amp; reports<span
            class="cat-chevron">&#9656;</span></summary>
        <div class="sidebar-cat-links"><a href="../report.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="full seo audit">Full SEO audit</a><a href="competitor-comparison.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="competitor comparison">Competitor comparison</a>
        </div>
      </details>
      <details class="sidebar-cat" open>
        <summary><span class="sidebar-cat-dot" style="background:var(--amber);"></span>Technical SEO<span
            class="cat-chevron">&#9656;</span></summary>
        <div class="sidebar-cat-links"><a href="bulk-indexability-checker.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="bulk url indexability checker">Bulk URL indexability checker</a><a
            href="<?= SITE_URL ?>/tools/robots-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="robots.txt generator">Robots.txt generator</a><a href="<?= SITE_URL ?>/tools/schema-generator.html"
            target="_blank" rel="noopener" class="sidebar-tool-link" data-tool-name="schema generator">Schema
            generator</a><a href="<?= SITE_URL ?>/tools/redirect-checker.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="redirect checker">Redirect checker</a><a href="<?= SITE_URL ?>/tools/broken-link-checker.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="broken link checker">Broken link checker</a><a
            href="<?= SITE_URL ?>/tools/backlink-checker.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="backlink checker">Backlink checker</a><a href="<?= SITE_URL ?>/tools/image-url-checker.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="image url checker">Image URL checker</a><a
            href="<?= SITE_URL ?>/tools/internal-link-suggestions.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="internal link suggestion tool">Internal link suggestion tool</a><a
            href="<?= SITE_URL ?>/tools/keyword-cannibalization-checker.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="keyword cannibalization checker">Keyword cannibalization checker</a><a
            href="<?= SITE_URL ?>/tools/search-intent-cluster.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="search intent cluster tool">Search intent cluster tool</a><a
            href="<?= SITE_URL ?>/tools/keyword-research-tool.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="ecommerce keyword research tool">eCommerce keyword research tool</a><a
            href="<?= SITE_URL ?>/tools/programmatic-seo-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="programmatic seo page generator">Programmatic SEO page generator</a></div>
      </details>
      <details class="sidebar-cat" open>
        <summary><span class="sidebar-cat-dot" style="background:var(--green);"></span>Product &amp; e-commerce
          feeds<span class="cat-chevron">&#9656;</span></summary>
        <div class="sidebar-cat-links"><a href="<?= SITE_URL ?>/tools/multi-channel-feed-generator.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="multi-channel feed generator">Multi-channel feed generator</a><a
            href="<?= SITE_URL ?>/tools/merchant-feed-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="google merchant feed generator">Google Merchant feed generator</a><a
            href="<?= SITE_URL ?>/tools/facebook-product-feed-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="facebook product feed generator">Facebook product feed generator</a><a
            href="<?= SITE_URL ?>/tools/pinterest-product-feed-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="pinterest product feed generator">Pinterest product feed generator</a><a
            href="<?= SITE_URL ?>/tools/category-taxonomy-finder.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="google product category finder">Google product category finder</a><a
            href="<?= SITE_URL ?>/tools/competitor-product-research.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="competitor product research">Competitor product research</a><a
            href="<?= SITE_URL ?>/tools/merchant-feed-validator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="merchant feed validator">Merchant feed validator</a><a href="<?= SITE_URL ?>/tools/gtin-validator.html"
            target="_blank" rel="noopener" class="sidebar-tool-link" data-tool-name="gtin / ean / upc validator">GTIN /
            EAN / UPC validator</a><a href="<?= SITE_URL ?>/tools/product-title-optimizer.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="product title optimizer">Product title optimizer</a><a
            href="<?= SITE_URL ?>/tools/product-description-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="seo product description generator">SEO product description generator</a><a
            href="<?= SITE_URL ?>/tools/slug-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="slug generator">Slug generator</a><a href="<?= SITE_URL ?>/tools/keyword-density.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="keyword density">Keyword density</a></div>
      </details>
      <details class="sidebar-cat" open>
        <summary><span class="sidebar-cat-dot" style="background:var(--pink-500);"></span>Content &amp; AI search<span
            class="cat-chevron">&#9656;</span></summary>
        <div class="sidebar-cat-links"><a href="<?= SITE_URL ?>/tools/ai-crawler-checker.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="ai crawler &amp;amp; llms.txt checker">AI crawler &amp;amp;
            llms.txt checker</a><a href="<?= SITE_URL ?>/tools/readability-counter.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="readability counter">Readability counter</a><a
            href="<?= SITE_URL ?>/tools/blog-topic-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="blog topic generator">Blog topic generator</a><a href="<?= SITE_URL ?>/tools/discover-headline-generator.html"
            target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="google discover headline generator">Google Discover headline generator</a><a
            href="<?= SITE_URL ?>/tools/ai-overview-optimizer.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="ai overview optimizer">AI Overview optimizer</a><a href="<?= SITE_URL ?>/tools/geo-checker.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="geo checker">GEO checker</a><a
            href="<?= SITE_URL ?>/tools/featured-snippet-optimizer.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="featured snippet optimizer">Featured snippet optimizer</a><a
            href="<?= SITE_URL ?>/tools/topical-coverage-calculator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="topical coverage calculator">Topical coverage calculator</a><a
            href="<?= SITE_URL ?>/tools/meta-tag-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="meta tag generator">Meta tag generator</a></div>
      </details>
      <details class="sidebar-cat" open>
        <summary><span class="sidebar-cat-dot" style="background:var(--cyan-500);"></span>Sharing &amp;
          distribution<span class="cat-chevron">&#9656;</span></summary>
        <div class="sidebar-cat-links"><a href="<?= SITE_URL ?>/tools/serp-preview.html" target="_blank" rel="noopener"
            class="sidebar-tool-link" data-tool-name="serp preview">SERP preview</a><a href="<?= SITE_URL ?>/tools/open-graph-preview.html"
            target="_blank" rel="noopener" class="sidebar-tool-link" data-tool-name="open graph preview">Open Graph
            preview</a><a href="<?= SITE_URL ?>/tools/utm-builder.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="utm builder">UTM builder</a><a href="<?= SITE_URL ?>/tools/whatsapp-link-generator.html" target="_blank"
            rel="noopener" class="sidebar-tool-link" data-tool-name="whatsapp link generator">WhatsApp link
            generator</a><a href="<?= SITE_URL ?>/tools/rss-feed-generator.html" target="_blank" rel="noopener" class="sidebar-tool-link"
            data-tool-name="rss feed generator">RSS feed generator</a></div>
      </details>
      <div class="sidebar-empty-msg" id="sidebar-empty-msg">No tools match your search.</div>
    </aside>
  </div>

  <!-- SEO FAQ SECTION -->
  <div class="wrap-mid" id="seo-faq" data-noprint style="padding-top:40px;padding-bottom:10px;">
    <div class="card" style="padding:32px;">
      <h2 style="font-size:22px;margin-bottom:20px;letter-spacing:-0.01em;">Frequently Asked Questions</h2>

      <details class="faq-item" style="margin-bottom:16px;border-bottom:1px solid var(--border);padding-bottom:16px;">
        <summary
          style="font-weight:700;font-size:15px;cursor:pointer;color:var(--ink);list-style:none;display:flex;justify-content:space-between;align-items:center;">
          What is the SEO Audit Report and how does it work? <span style="color:var(--muted-2);font-size:20px;">+</span>
        </summary>
        <p class="muted" style="margin-top:12px;font-size:14.5px;line-height:1.6;">The SEO Audit Report is a powerful,
          browser-based utility designed to streamline your SEO workflow. It processes your inputs entirely in your
          browser or through secure edge relays, delivering instant, accurate results without storing your data.</p>
      </details>

      <details class="faq-item" style="margin-bottom:16px;border-bottom:1px solid var(--border);padding-bottom:16px;">
        <summary
          style="font-weight:700;font-size:15px;cursor:pointer;color:var(--ink);list-style:none;display:flex;justify-content:space-between;align-items:center;">
          How do I use the SEO Audit Report? <span style="color:var(--muted-2);font-size:20px;">+</span>
        </summary>
        <p class="muted" style="margin-top:12px;font-size:14.5px;line-height:1.6;">Simply enter your URL or required
          data into the input field above and click the action button. The SEO Audit Report will automatically analyze
          your input and generate a comprehensive, exportable report or code snippet in seconds.</p>
      </details>

      <details class="faq-item" style="margin-bottom:16px;border-bottom:1px solid var(--border);padding-bottom:16px;">
        <summary
          style="font-weight:700;font-size:15px;cursor:pointer;color:var(--ink);list-style:none;display:flex;justify-content:space-between;align-items:center;">
          Is the SEO Audit Report completely free and unlimited? <span
            style="color:var(--muted-2);font-size:20px;">+</span>
        </summary>
        <p class="muted" style="margin-top:12px;font-size:14.5px;line-height:1.6;">Yes! Like all tools on Crawlie, the
          SEO Audit Report is 100% free to use. There are no paywalls, no login requirements, and absolutely no strict
          usage limits. You can run as many scans and generate as many reports as you need.</p>
      </details>

      <details class="faq-item" style="margin-bottom:0;padding-bottom:0;">
        <summary
          style="font-weight:700;font-size:15px;cursor:pointer;color:var(--ink);list-style:none;display:flex;justify-content:space-between;align-items:center;">
          Is my data safe and secure? <span style="color:var(--muted-2);font-size:20px;">+</span>
        </summary>
        <p class="muted" style="margin-top:12px;font-size:14.5px;line-height:1.6;">Absolutely. The SEO Audit Report runs
          its core logic locally in your browser. We do not store your website data, track your internal links, or keep
          a database of your reports.</p>
      </details>
    </div>
  </div>
  <div class="wrap-mid" style="padding-bottom:60px;" data-noprint>
    <div class="blog-slider-head">
      <div class="blog-slider-title">From the blog <span class="blog-pulse-dot" aria-hidden="true"></span></div>
      <div class="flex gap-8">
        <button type="button" class="blog-slider-nav" id="blog-slider-prev"
          aria-label="Previous article">&#8249;</button>
        <button type="button" class="blog-slider-nav" id="blog-slider-next" aria-label="Next article">&#8250;</button>
      </div>
    </div>
    <div class="blog-slider" id="blog-slider">
      <a href="blog/articles/manual-vs-sitemap-generator-comparison.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">Sitemap Generator vs. Doing It by Hand: Is It Worth Switching?</div>
          <div class="blog-slide-excerpt muted">A practical look at what Sitemap Generator actually saves you over doing
            XML sitemap manually, and when manual still makes sense.</div>
        </div>
      </a>
      <a href="blog/articles/xml-sitemap-pre-publish-checklist.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">The XML Sitemap Checklist: What to Verify Before You Publish</div>
          <div class="blog-slide-excerpt muted">A short, practical checklist for XML sitemap — the things worth checking
            every time, not just the first time.</div>
        </div>
      </a>
      <a href="blog/articles/xml-sitemap-faq.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">XML Sitemap FAQ: Questions People Actually Ask</div>
          <div class="blog-slide-excerpt muted">Straight answers to the questions that come up most often about XML
            sitemap.</div>
        </div>
      </a>
      <a href="blog/articles/does-xml-sitemap-still-matter.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">Does XML Sitemap Still Matter in 2026?</div>
          <div class="blog-slide-excerpt muted">A quick, honest look at whether XML sitemap is still worth the effort,
            or a holdover from an older era of SEO.</div>
        </div>
      </a>
      <a href="blog/articles/xml-sitemap-for-beginners.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">XML Sitemap for Beginners: The 5-Minute Primer</div>
          <div class="blog-slide-excerpt muted">New to XML sitemap? Here&#x27;s the short version — what it is, why
            it&#x27;s worth 10 minutes, and how to check it right now.</div>
        </div>
      </a>
      <a href="blog/articles/what-is-xml-sitemap-guide.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">What Is Sitemap Generator? A Practical Guide to XML Sitemap</div>
          <div class="blog-slide-excerpt muted">What Sitemap Generator actually does, why XML sitemap matters for SEO,
            and how to get it right from the start.</div>
        </div>
      </a>
      <a href="blog/articles/how-to-sitemap-generator-step-by-step.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">How to Use Sitemap Generator the Right Way (2026)</div>
          <div class="blog-slide-excerpt muted">A step-by-step walkthrough for using Sitemap Generator effectively, with
            the details most guides skip.</div>
        </div>
      </a>
      <a href="blog/articles/sitemap-generator-mistakes-and-best-practices.html" class="blog-slide-card"><img
          src="assets/blog-images/generated/technical_seo.png"
          alt="Illustration representing XML sitemap, related to the Sitemap Generator tool on Crawlie"
          class="blog-slide-img" loading="lazy" width="272" height="110">
        <div class="blog-slide-body">
          <div class="blog-slide-title">Sitemap Generator: Common Mistakes and Best Practices</div>
          <div class="blog-slide-excerpt muted">The most common mistakes teams make with Sitemap Generator, and the
            practices that actually fix them.</div>
        </div>
      </a>
    </div>
  </div>


  <footer class="footer wrap" data-noprint>
    <div class="footer-grid">
      <div>
        <a href="index.html" class="brand" style="margin-bottom:14px;"><span class="brand-mark"><i></i></span><span
            class="brand-name">Crawlie</span></a>
        <p class="muted" style="font-size:14px;line-height:1.6;max-width:260px;margin-top:14px;">A free, no-login SEO
          audit tool and toolbox that runs entirely in your browser.</p>
      </div>
      <div>
        <h4>Product</h4><a href="index.html">Free SEO audit</a><a href="tools.html">Free tools</a><a
          href="blog/index.html">Blog</a><a href="report.html?url=https%3A%2F%2Fexample.com">Sample report</a>
      </div>
      <div>
        <h4>Tools</h4><a href="tools/sitemap-generator.html">Sitemap generator</a><a
          href="tools/robots-generator.html">Robots.txt generator</a><a href="tools/backlink-checker.html">Backlink
          checker</a><a href="tools/ai-crawler-checker.html">AI crawler & llms.txt checker</a>
      </div>
      <div>
        <h4>Company</h4><a href="about.html">About</a><a href="contact.html">Contact</a><a
          href="privacy-policy.html">Privacy Policy</a>
      </div>
    </div>
    <div class="footer-bottom">
      <span>&copy; <span data-year></span> Crawlie. All checks run locally in your browser.</span>
      <span>Built with care for people who'd rather fix than guess.</span>
    </div>
  </footer>

  <style>
    .score-summary-grid {
      display: grid;
      grid-template-columns: 230px 1fr;
      gap: 30px;
      align-items: center;
    }

    @media (max-width:700px) {
      .score-summary-grid {
        grid-template-columns: 1fr;
      }

      .score-summary-grid>div:first-child {
        margin-bottom: 10px;
      }
    }

    .metric-row {
      display: flex;
      justify-content: space-between;
      padding: 8px 0;
      border-bottom: 1px solid #f1edfa;
    }

    .metric-row:last-child {
      border-bottom: none;
    }

    .issue-row {
      border: 1px solid #f1edfa;
      border-radius: 16px;
      overflow: hidden;
    }

    .issue-toggle {
      display: flex;
      align-items: center;
      gap: 16px;
      width: 100%;
      padding: 15px 16px;
      border: none;
      background: #fff;
      cursor: pointer;
      font-family: inherit;
      text-align: left;
    }

    .issue-toggle:hover {
      background: var(--violet-50);
    }

    .issue-chevron {
      flex-shrink: 0;
      color: var(--muted-2);
      transition: transform .15s;
    }

    .issue-row.is-open .issue-chevron {
      transform: rotate(180deg);
    }

    .issue-detail {
      padding: 0 16px 16px 62px;
      background: #fff;
    }
  </style>

  <script src="assets/main.js?v=2"></script>
  <script src="assets/audit-engine.js"></script>
  <script src="assets/report-export.js"></script>
  <script>
    (function () {
      var $ = function (id) { return document.getElementById(id); };
      var statuses = ['Fetching your page...', 'Checking meta tags...', 'Measuring page structure...', 'Testing mobile readiness...', 'Scanning links & images...', 'Checking structured data...', 'Building your report...'];
      var currentReport = null, statusTimer = null, scanToken = 0;

      function showState(name) {
        ['scanning', 'fallback', 'results'].forEach(function (s) {
          $('state-' + s).classList.toggle('hidden', s !== name);
        });
      }

      function paramUrl() {
        var p = new URLSearchParams(window.location.search);
        return p.get('url') || '';
      }

      function startScan(url) {
        window.history.replaceState({}, '', 'report.php?url=' + encodeURIComponent(url));
        $('audit-url-input').value = url.replace(/^https?:\/\//, '');
        // Critical: clear any leftover pasted HTML and prior report before starting a new
        // scan. Without this, a failed re-scan for a different site could silently re-analyze
        // whatever was left in the textarea from a previous site's paste-fallback attempt.
        $('fallback-html').value = '';
        $('backend-url-status').textContent = '';
        currentReport = null;
        // Each scan gets its own token. If a slower, earlier scan's fetch resolves after a
        // newer scan has already started, its result is discarded instead of overwriting
        // whatever the user is now looking at.
        var myToken = ++scanToken;
        showState('scanning');
        $('scan-target').textContent = url;
        var i = 0;
        clearInterval(statusTimer);
        $('scan-status').textContent = statuses[0];
        statusTimer = setInterval(function () { i = (i + 1) % statuses.length; $('scan-status').textContent = statuses[i]; }, 480);

        var minWait = new Promise(function (res) { setTimeout(res, 2600); });
        CrawlieEngine.fetchPage(url).then(function (result) {
          minWait.then(function () {
            if (myToken !== scanToken) return; // a newer scan has since started; ignore this stale result
            clearInterval(statusTimer);
            if (result.ok) {
              var metrics = CrawlieEngine.analyzeHtml(result.html, result.url);
              metrics.fetchMs = result.fetchMs;
              renderResults(CrawlieEngine.buildReport(metrics));
            } else {
              var count = result.attemptCount || 1;
              var detail = (result.attempts && result.attempts.length)
                ? '<br><span class="mono" style="font-size:12px;">' + result.attempts.map(esc).join('<br>') + '</span>'
                : esc(result.error);
              var backendFailed = result.attempts && result.attempts.some(function (a) { return a.indexOf('your-backend:') === 0; });
              var backendHint = backendFailed
                ? '<br><br><strong>Note:</strong> you have a custom fetch backend URL saved, and it failed too. If you haven\'t actually deployed the Cloudflare Worker from this download\'s <code class="mono">backend/</code> folder yet, open "Using your own fetch backend?" below and clear it — an unreachable saved URL just adds a failed attempt to every scan. If you have deployed it, double-check the URL was copied correctly.'
                : '';
              $('fallback-reason').innerHTML = 'We tried ' + count + ' different way' + (count > 1 ? 's' : '') + ' to fetch <strong>' + esc(url) + '</strong> and every one was blocked or timed out:' + detail + '<br><br>This usually means the site itself blocks automated/proxy traffic (common on news sites) — the paste option below always works instead.' + backendHint;
              showState('fallback');
            }
          });
        });
      }

      function renderResults(report) {
        currentReport = report;
        var m = report.metrics;
        showState('results');
        $('result-url').textContent = m.url;
        $('result-date').textContent = 'Generated ' + report.generatedAt.toLocaleString();

        var col = report.overall >= 80 ? '#18a877' : report.overall >= 60 ? '#ef9d1d' : '#f5476b';
        $('score-donut').style.background = 'conic-gradient(' + col + ' ' + (report.overall * 3.6) + 'deg, #ece7f7 0)';
        $('score-number').textContent = report.overall;
        $('score-grade-label').textContent = 'SEO score · grade ' + CrawlieExport.grade(report.overall);

        var barsHtml = '';
        Object.keys(CrawlieExport.CAT_LABELS).forEach(function (k) {
          var c = report.categories[k];
          var bc = c.score >= 80 ? 'var(--green)' : c.score >= 60 ? 'var(--amber)' : 'var(--red)';
          barsHtml += '<div class="bar-row" style="margin-bottom:0;"><div class="bar-head"><span>' + CrawlieExport.CAT_LABELS[k] + '</span><span style="color:' + bc + '">' + c.score + '</span></div><div class="bar-track"><div class="bar-fill" style="width:' + c.score + '%;background:' + bc + ';"></div></div></div>';
        });
        $('category-bars').innerHTML = barsHtml;

        $('issue-count').textContent = report.issues.length + ' found';
        if (!report.issues.length) {
          $('issues-list').innerHTML = '<div class="muted" style="padding:20px 0;">No issues detected — nice work.</div>';
        } else {
          $('issues-list').innerHTML = report.issues.map(function (iss, i) {
            var badgeClass = iss.severity === 'critical' ? 'badge-critical' : iss.severity === 'warning' ? 'badge-warning' : 'badge-good';
            var numBg = iss.severity === 'critical' ? '#fde6ec' : iss.severity === 'warning' ? '#fdf0db' : '#e3f7ee';
            var numFg = iss.severity === 'critical' ? '#f5476b' : iss.severity === 'warning' ? '#cf8410' : '#18a877';
            return '<div class="issue-row">' +
              '<button type="button" class="issue-toggle" aria-expanded="false">' +
              '<div style="width:30px;height:30px;border-radius:9px;background:' + numBg + ';color:' + numFg + ';display:grid;place-items:center;font-weight:800;font-size:14px;flex-shrink:0;">' + (i + 1) + '</div>' +
              '<div style="flex:1;min-width:0;text-align:left;"><div style="font-weight:700;font-size:15px;">' + esc(iss.title) + '</div><div class="muted" style="font-size:12.5px;">' + esc(iss.category) + '</div></div>' +
              '<span class="badge ' + badgeClass + '">' + iss.severity + '</span>' +
              '<svg class="issue-chevron" width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
              '</button>' +
              '<div class="issue-detail hidden"><p class="muted" style="font-size:13.5px;line-height:1.55;margin:0;">' + esc(iss.detail) + '</p></div>' +
              '</div>';
          }).join('');
          $('issues-list').querySelectorAll('.issue-toggle').forEach(function (btn) {
            btn.addEventListener('click', function () {
              var row = btn.closest('.issue-row');
              var detail = row.querySelector('.issue-detail');
              var expanded = btn.getAttribute('aria-expanded') === 'true';
              btn.setAttribute('aria-expanded', String(!expanded));
              detail.classList.toggle('hidden', expanded);
              row.classList.toggle('is-open', !expanded);
            });
          });
        }

        var metricRows = [
          ['Word count', m.wordCount], ['Title length', m.titleLen + ' chars (ideal 15&ndash;65)'],
          ['Meta description length', m.descLen + ' chars (ideal 50&ndash;160)'], ['H1 tags found', m.h1Count],
          ['Images missing alt text', m.imgsMissingAlt + ' of ' + m.imgCount],
          ['Internal / external links', m.linkInternal + ' / ' + m.linkExternal],
          ['HTTPS', m.isHttps ? 'Yes' : 'No'], ['Structured data blocks', m.structuredDataCount],
          ['Open Graph tags complete', m.ogComplete ? 'Yes' : 'No'],
          ['Readability (Flesch)', m.readability.flesch + ' — ' + m.readability.grade],
          ['Estimated HTML size', m.sizeKb + ' KB']
        ];
        $('metrics-list').innerHTML = metricRows.map(function (r) {
          return '<div class="metric-row"><span class="muted">' + r[0] + '</span><span style="font-weight:700;">' + r[1] + '</span></div>';
        }).join('');

        $('preview-title').textContent = m.title || '(missing title tag)';
        $('preview-url').textContent = m.url.replace(/^https?:\/\//, '').replace(/\/$/, '');
        $('preview-desc').textContent = m.description || '(missing meta description — Google will auto-generate a snippet from page content.)';
      }

      function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }

      $('audit-bar').addEventListener('submit', function (e) {
        e.preventDefault();
        var v = $('audit-url-input').value.trim();
        if (!v) return;
        startScan(CrawlieEngine.normalizeUrl(v));
      });

      $('fallback-retry').addEventListener('click', function () { startScan(CrawlieEngine.normalizeUrl(paramUrl())); });

      (function initBackendSettings() {
        var saved = CrawlieEngine.getCustomBackend();
        if (saved) $('backend-url-input').value = saved;
        $('backend-url-save').addEventListener('click', function () {
          var v = $('backend-url-input').value.trim();
          if (!v) { $('backend-url-status').textContent = 'Enter a URL first.'; return; }
          CrawlieEngine.setCustomBackend(v);
          $('backend-url-status').textContent = 'Saved — it will be tried first on your next scan.';
          $('backend-url-status').style.color = 'var(--green)';
        });
        $('backend-url-clear').addEventListener('click', function () {
          CrawlieEngine.setCustomBackend('');
          $('backend-url-input').value = '';
          $('backend-url-status').textContent = 'Cleared — back to using public relays only.';
          $('backend-url-status').style.color = 'var(--muted-2)';
        });
      })();
      $('fallback-analyze').addEventListener('click', function () {
        var html = $('fallback-html').value;
        if (!html.trim()) return;
        var url = CrawlieEngine.normalizeUrl(paramUrl()) || 'https://your-page.example';
        var metrics = CrawlieEngine.analyzeHtml(html, url);
        renderResults(CrawlieEngine.buildReport(metrics));
      });

      $('btn-print').addEventListener('click', function () { window.print(); });
      $('btn-download-pdf').addEventListener('click', function () { if (currentReport) CrawlieExport.downloadPdf(currentReport); });
      $('btn-download-html').addEventListener('click', function () { if (currentReport) CrawlieExport.downloadHtml(currentReport); });

      var initial = paramUrl();
      if (initial) startScan(CrawlieEngine.normalizeUrl(initial));
    })();
  </script>
  <!-- Mobile Sticky Ad -->
  <div class="ad-container-mobile-sticky" data-noprint>
    <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXX"
      crossorigin="anonymous"></script>
    <ins class="adsbygoogle" style="display:inline-block;width:320px;height:50px" data-ad-client="ca-pub-XXXXX"
      data-ad-slot="0987654321"></ins>
    <script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
  </div>
</body>

</html>