<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Illucrum blog]]></title><description><![CDATA[Specialist SEO audits that show you exactly what to fix next. For SaaS, e-commerce, and growing SMEs. Reports in 5 to 8 days.]]></description><link>https://blog.illucrum.com</link><image><url>https://cdn.hashnode.com/uploads/logos/6938690abe359741ad261496/75042e2a-e853-42f9-ba9e-11f02f0b1aff.png</url><title>Illucrum blog</title><link>https://blog.illucrum.com</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 13:26:12 GMT</lastBuildDate><atom:link href="https://blog.illucrum.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[SEO Checklist (2026)]]></title><description><![CDATA[A website SEO audit is an inventory, not an opinion. You go through the site one layer at a time, record what you find with evidence attached, and end up with a list you can sequence. The value is in ]]></description><link>https://blog.illucrum.com/seo-checklist-2026</link><guid isPermaLink="true">https://blog.illucrum.com/seo-checklist-2026</guid><category><![CDATA[SEO]]></category><category><![CDATA[checklist]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Mon, 24 Aug 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/8aa3ccb6-0856-4cf7-a5e3-a2f596cc651c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A website SEO audit is an inventory, not an opinion. You go through the site one layer at a time, record what you find with evidence attached, and end up with a list you can sequence. The value is in the record. A vague sense that "the site could be faster" is not a finding; a measured LCP of 4.8 seconds on the main service page is.</p>
<p><strong>In short:</strong> A full website SEO audit covers technical health, on-page elements, keyword performance, backlinks, competitors, local presence, conversion signals, and AI search visibility. All 52 checks below can be run with Google Search Console, PageSpeed Insights, Chrome DevTools, a free crawler, and a handful of free validators.</p>
<hr />
<h2>What do you need before you start?</h2>
<p>Everything here can be done on free tools. Two of them are not optional: without verified Google Search Console access you cannot complete roughly a quarter of the checks, and without Google Analytics you cannot complete the engagement checks at all.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Used for</th>
<th>Cost</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://search.google.com/search-console">Google Search Console</a></td>
<td>Index coverage, queries, positions, links, Core Web Vitals field data</td>
<td>Free, requires domain verification</td>
</tr>
<tr>
<td><a href="https://pagespeed.web.dev/">PageSpeed Insights</a></td>
<td>Performance scores, Core Web Vitals, image and script diagnostics</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://developer.chrome.com/docs/devtools/">Chrome DevTools</a></td>
<td>Network tab, console, device emulation, rendered DOM</td>
<td>Free, built into Chrome</td>
</tr>
<tr>
<td><a href="https://www.screamingfrog.co.uk/seo-spider/">Screaming Frog SEO Spider</a></td>
<td>Crawl, status codes, titles, headings, redirect chains, orphan detection</td>
<td>Free up to 500 URLs</td>
</tr>
<tr>
<td><a href="https://search.google.com/test/rich-results">Google Rich Results Test</a></td>
<td>Structured data validation and rendered HTML</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://validator.schema.org/">Schema Markup Validator</a></td>
<td>Schema validation beyond Google's rich result types</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://www.ssllabs.com/ssltest/">SSL Labs Server Test</a></td>
<td>Certificate validity, expiry, configuration grade</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://analytics.google.com/">Google Analytics 4</a></td>
<td>Engagement rate, average engagement time per page</td>
<td>Free, requires property access</td>
</tr>
<tr>
<td><a href="https://www.google.com/business/">Google Business Profile</a></td>
<td>Local listing completeness, reviews, categories</td>
<td>Free, local businesses only</td>
</tr>
<tr>
<td><a href="https://whitespark.ca/local-citation-finder/">Whitespark Local Citation Finder</a></td>
<td>Directory listings and NAP consistency</td>
<td>Free tier</td>
</tr>
<tr>
<td><a href="https://www.seoptimer.com/">SEOptimer</a></td>
<td>Quick crawl summary and domain strength reference</td>
<td>Free tier</td>
</tr>
</tbody></table>
<p>Open a spreadsheet before you open a tool. Four columns: check number, finding, evidence (a URL, a number, or a screenshot), and severity. Fill it as you go rather than at the end, because by check 40 you will not remember what check 6 turned up.</p>
<p>One more decision to make now. Pick your sample pages and use the same ones throughout: the homepage, your two most commercially important pages, one blog or informational page, and the contact page. Auditing the homepage alone tells you almost nothing, because the homepage is usually the one page that got attention.</p>
<hr />
<h2>Section 1: How do you check technical SEO?</h2>
<p>Technical checks come first because everything downstream depends on them. There is no point rewriting a title tag on a page Google has decided not to index.</p>
<h3>1. Page speed, mobile and desktop</h3>
<p>Run each of your five sample pages through PageSpeed Insights twice, once with the mobile strategy and once with desktop. Record both Performance scores. Judge the site on the mobile figure; it is almost always the lower of the two and it is the one that matches how Google crawls.</p>
<p><strong>Record:</strong> mobile and desktop score per page, plus the top three opportunities listed for each.</p>
<h3>2. Core Web Vitals</h3>
<p>From the same reports, record LCP, INP, and CLS. Use the field data at the top of the report, which comes from real Chrome users over the previous 28 days, in preference to the lab data below it. If the field section is missing, the site does not have enough traffic to appear in the Chrome UX Report; note that, and treat the lab numbers as indicative only. Then open Search Console, Experience, Core Web Vitals for the site-wide view.</p>
<p>Thresholds: LCP at or under 2.5 seconds, INP at or under 200 milliseconds, CLS at or under 0.1.</p>
<p><strong>Record:</strong> the three values per page, whether they are field or lab, and the URL counts in each Search Console status band.</p>
<h3>3. Mobile friendliness</h3>
<p>Open DevTools, switch on device emulation, and set the viewport to a common phone size such as 390 by 844. Load all five sample pages. Look for horizontal scrolling, content wider than the viewport, text too small to read without zooming, and navigation or forms that break. Check tap targets on the primary navigation and main buttons; Google's guidance is 48 by 48 CSS pixels with 8 pixels of spacing.</p>
<p><strong>Record:</strong> per page, whether the layout holds, plus screenshots of anything broken and a list of undersized tap targets.</p>
<h3>4. HTTPS and SSL certificate</h3>
<p>Confirm the site loads over HTTPS. Request the HTTP version and watch the DevTools Network tab to see whether it redirects to HTTPS in a single hop. Click the padlock for certificate issuer, coverage, and expiry date. Run the domain through <a href="https://www.ssllabs.com/ssltest/">SSL Labs</a> for a configuration grade; the scan takes a couple of minutes.</p>
<p><strong>Record:</strong> redirect behavior and hop count, certificate expiry, issuer, SSL Labs grade.</p>
<h3>5. XML sitemap</h3>
<p>Open <code>yourdomain.com/sitemap.xml</code>. Confirm it is well-formed XML and returns 200. Sample 15 to 20 of the URLs listed and check each one returns 200, is the canonical version, and is not set to <code>noindex</code>. Confirm the sitemap excludes admin pages, cart or checkout pages, thank-you pages, and parameter URLs. Then compare the URL count against Search Console, Indexing, Sitemaps.</p>
<p><strong>Record:</strong> URL count, number of sampled URLs failing and why, Search Console discovered count, last read date.</p>
<h3>6. Robots.txt</h3>
<p>Open <code>yourdomain.com/robots.txt</code> in a browser and read the whole file. Confirm it returns 200 rather than a 404. Look for <code>Disallow: /</code>, which blocks the entire site, and for any rule that catches service pages, the blog, or the CSS and JavaScript needed to render pages. Confirm a <code>Sitemap:</code> directive is present and points at a live URL.</p>
<p><strong>Record:</strong> status code, full file contents, any Disallow rule affecting content, whether the sitemap is declared.</p>
<h3>7. Canonical tags</h3>
<p>On each sample page, view the source and find <code>&lt;link rel="canonical"&gt;</code>. Confirm it exists, uses an absolute HTTPS URL, and points at the page itself. Then test the duplicate access paths: with and without a trailing slash, with a tracking parameter appended, and the print version if one exists. Each should either return the same canonical or redirect.</p>
<p><strong>Record:</strong> per page, whether the canonical is present, self-referencing, and absolute; plus any duplicate path that returns 200 with no canonical.</p>
<h3>8. Structured data</h3>
<p>Run the homepage and one URL of each page type through the <a href="https://search.google.com/test/rich-results">Rich Results Test</a>. Record the schema types detected, the error count, and the warning count. Then run the same URLs through the <a href="https://validator.schema.org/">Schema Markup Validator</a>, which checks against schema.org rather than only Google's supported rich result types. At minimum you are looking for <code>Organization</code> on the homepage and a page-type schema elsewhere.</p>
<p><strong>Record:</strong> types detected per page type, errors, warnings, and any page type with no structured data at all.</p>
<h3>9. Crawl errors and index coverage</h3>
<p>In Search Console, go to Indexing, then Pages. Record the Indexed and Not indexed totals. Open the "Why pages aren't indexed" breakdown and record the count against each reason, paying attention to <code>Crawled - currently not indexed</code>, <code>Discovered - currently not indexed</code>, <code>Soft 404</code>, <code>Excluded by noindex tag</code>, and the duplicate reasons. Then confirm your commercially important pages appear in the indexed set.</p>
<p><strong>Record:</strong> indexed count, not-indexed count, the full reason breakdown, and any key page found in the not-indexed set.</p>
<h3>10. Redirect chains and 4xx errors</h3>
<p>Crawl the site with Screaming Frog. Sort by status code and flag every 4xx and 5xx that is linked from somewhere on the site or listed in the sitemap. Then open Reports, Redirects, Redirect Chains; anything passing through more than one hop is a chain. Check whether permanent moves use 301 rather than 302, and flag any URL redirecting into a loop.</p>
<p><strong>Record:</strong> 4xx URLs with the pages that link to them, 5xx URLs, each chain with its hop count, and any 302 used for a permanent move.</p>
<h3>11. Duplicate and thin pages</h3>
<p>In the crawl, use the duplicate detection on titles, meta descriptions, and H1s to find pages sharing identical elements. Then look at the word count column and open anything unusually short. The question is not whether a page hits a number; it is whether the page does its job. A 200-word contact page is fine. A 200-word service page competing against 1,500-word competitor pages is not.</p>
<p><strong>Record:</strong> pages sharing duplicate titles or descriptions, and a list of pages that are thin relative to what the query requires.</p>
<h3>12. Hreflang</h3>
<p>If the site is monolingual, mark this N/A and move on. Otherwise view the source on a page that exists in several languages and record the <code>&lt;link rel="alternate" hreflang="..."&gt;</code> set. Check the language and region codes are valid, that each page references itself, that pairs are reciprocal, and that an <code>x-default</code> exists.</p>
<p><strong>Record:</strong> hreflang set per sampled URL, missing reciprocals, invalid codes, broken target URLs.</p>
<hr />
<h2>Section 2: How do you check on-page SEO?</h2>
<p>On-page work is the cheapest part of SEO to fix and the easiest part to get wrong at scale, because most of it is generated by a template that nobody has looked at since launch.</p>
<h3>13. Title tags</h3>
<p>Export the title column from your crawl. Check three things: every page has one, no two pages share one, and each describes the specific page rather than the brand. Length matters mainly because Google truncates and rewrites long titles, so aim for roughly 50 to 60 characters. Front-load the term the page is actually competing for.</p>
<p><strong>Record:</strong> missing titles, duplicate titles, titles over 60 characters, and titles that name only the brand.</p>
<h3>14. Meta descriptions</h3>
<p>Export the meta description column. Check for missing, duplicated, and auto-generated descriptions on your commercially important pages. Be realistic about what this is worth: Google rewrites the majority of meta descriptions it is given, and the tag is not a ranking factor. It is a click-through asset. Write them properly for the top pages and do not spend a week rewriting them site-wide.</p>
<p><strong>Record:</strong> missing and duplicate descriptions on key pages only, and whether each key page's description says something specific.</p>
<h3>15. Heading structure</h3>
<p>For each sample page, use the crawl's H1 and H2 columns or read the source directly. Check there is exactly one H1, that it describes the page, and that headings descend in order without skipping levels. Then read the H2s on their own; they should form a readable outline of the page. Generic H2s such as "Our approach" and "Why choose us" tell a reader and a search engine nothing.</p>
<p><strong>Record:</strong> pages with no H1 or multiple H1s, hierarchy breaks, and the H2 outline for each key page.</p>
<h3>16. Image alt text</h3>
<p>In the crawl, open the Images tab and filter to "Missing Alt Text". Then open a sample page and read the alt attributes that do exist. You are checking for three failure modes: missing entirely, filename dumped in as alt text ("IMG_4471.jpg"), and keyword stuffing. Decorative images should carry an empty <code>alt=""</code> rather than a description.</p>
<p><strong>Record:</strong> count of images missing alt text, count with filename or stuffed alt text, and whether decorative images are correctly marked empty.</p>
<h3>17. Content quality and depth</h3>
<p>Read your key pages properly, as a prospective customer would. Ask whether the page answers the questions someone arriving from search would have, whether it contains anything specific (numbers, process detail, examples, constraints), and whether the reader would have to go elsewhere to actually understand the topic. Word count is a symptom, not a target; a thin page is usually short, but making it longer does not make it good.</p>
<p><strong>Record:</strong> per key page, a one-line judgement on completeness and a list of the questions it fails to answer.</p>
<h3>18. Internal linking</h3>
<p>In the crawl, look at the Inlinks column for each page. Check that key commercial pages receive multiple internal links from relevant content rather than only from the header and footer. Sample the anchor text used and note how much of it is "read more", "click here", or the bare URL. Then use Reports, Orphan Pages (this requires connecting the Search Console API before crawling) to find pages nothing links to.</p>
<p><strong>Record:</strong> inlink count for the top ten commercial pages, anchor text patterns, and the orphan list.</p>
<h3>19. URL structure</h3>
<p>Export the URL list and review 30 or so across page types. You are looking for lowercase characters, hyphens rather than underscores, absence of avoidable parameters, readable slugs, and sensible length. The real finding is usually inconsistency: some URLs hyphenated and some not, some with trailing slashes and some without, blog posts with dates in the path and service pages without.</p>
<p><strong>Record:</strong> the conventions in use per page type, and every place they conflict.</p>
<h3>20. Open Graph and social tags</h3>
<p>View the source on each page type and record whether <code>og:title</code>, <code>og:description</code>, <code>og:image</code>, <code>og:url</code>, <code>og:type</code>, and the Twitter Card tags are present. Confirm the <code>og:image</code> URL actually resolves and is at least 1200 by 630 pixels. The <a href="https://developers.facebook.com/tools/debug/">Facebook Sharing Debugger</a> will render the preview and list missing tags.</p>
<p><strong>Record:</strong> tag presence per template, image dimensions, and any templates sharing one generic og:image.</p>
<h3>21. Content freshness</h3>
<p>In Search Console, use URL Inspection on your key pages to see when Google last crawled each one. Separately, look at the site itself: when was the last blog post published, do case studies reference work from three years ago, do service pages describe an offer you no longer sell? Freshness is not a virtue in itself. Stale and wrong is the problem.</p>
<p><strong>Record:</strong> last crawl date per key page, last publish date on the blog, and a list of pages containing outdated claims.</p>
<h3>22. Keyword placement</h3>
<p>For each key page, work out what it is actually trying to rank for, then check whether that phrase appears in the title, the H1, the first paragraph, and at least one H2. This is a coverage check, not a density calculation; keyword density targets are folklore and have not been a meaningful signal for years. What you are looking for is a page that never states plainly what it is about.</p>
<p><strong>Record:</strong> per key page, the intended query and which of the four positions it appears in.</p>
<p>If working through this is more time than you want to spend on your own site, an <a href="https://illucrum.com/seo-audit/">SEO audit</a> covers the same ground and arrives prioritized.</p>
<hr />
<h2>Section 3: How do you check keyword performance?</h2>
<p>Everything so far has been about the site. This section is about what the site has actually earned. All of it comes out of Search Console.</p>
<h3>23. Ranking keywords overview</h3>
<p>Go to Performance, Search results, and set the date range to the last three months. Switch on all four metric columns: clicks, impressions, CTR, and average position. Sort by impressions and read the top 20 queries. The question to answer is whether these are queries from people who could buy something, or whether they are accidental.</p>
<p><strong>Record:</strong> total clicks and impressions, the top 20 queries with position and CTR, and how many of them are commercially relevant.</p>
<h3>24. Striking distance keywords</h3>
<p>In the same report, add a position filter for greater than 3 and less than 21, then sort by impressions. These are queries where the site already ranks but sits below the click-through cliff. Cross-reference each with the page that ranks for it, using the Pages tab.</p>
<p><strong>Record:</strong> the striking distance list with query, position, impressions, and the ranking URL for each.</p>
<h3>25. Local keyword visibility</h3>
<p>Skip this if the business does not serve a geographic market. Otherwise, filter queries containing your city or region name and note the positions. Then run three or four service-plus-location searches manually in an incognito window and note whether the site appears in the local pack, in the organic results, or nowhere.</p>
<p><strong>Record:</strong> local query list with positions, plus local pack placement for each manual search.</p>
<h3>26. Search intent alignment</h3>
<p>Take your top 10 non-branded queries and search each one in an incognito window. Look at what is ranking: are the top results service pages, blog posts, comparison articles, or directory listings? Then compare that with the page type you have pointed at the query. A service page competing in a results set made entirely of guides is misaligned, and no amount of on-page work will fix it.</p>
<p><strong>Record:</strong> per query, the dominant result format, your page type, and whether they match.</p>
<h3>27. Keyword gap against competitors</h3>
<p>Take the competitors you identify in check 34. Search 10 to 15 of your core service terms manually and record who ranks where. Where a competitor ranks and you do not appear at all, open their ranking page and note what it is: a dedicated service page, a location page, a guide, a comparison. That is the gap, and it is usually a page type rather than a keyword.</p>
<p><strong>Record:</strong> query-by-query rankings for you and each competitor, and the page types they have that you do not.</p>
<h3>28. Branded versus non-branded split</h3>
<p>In the Performance report, filter queries containing your brand name and record the clicks. Then invert the filter to exclude the brand and record the clicks. Calculate the split. A site where 90% of organic clicks are branded is not being found by anybody new; search is working as a switchboard for people who already know you.</p>
<p><strong>Record:</strong> branded clicks, non-branded clicks, and the percentage split.</p>
<hr />
<h2>Section 4: How do you check the backlink profile?</h2>
<p>Search Console's Links report is limited compared with a paid backlink tool, but it is accurate about your own site, which is what matters here.</p>
<h3>29. Referring domains</h3>
<p>Go to Links, then Top linking sites. Record the total number of linking sites and scan the list. What you want to know is whether links come from a spread of real, relevant sites, or whether the count is inflated by one directory network that has syndicated the same listing 40 times.</p>
<p><strong>Record:</strong> total linking sites, total external links, and the top 20 linking domains with a note on what each one is.</p>
<h3>30. Toxic and spammy links</h3>
<p>Work through the linking domains list and open anything you do not recognize. You are looking for link farms, scraped content sites, foreign-language pages unrelated to the business, and adult or gambling sites. Most sites have some of this and it is usually harmless; Google ignores the majority of low-quality links. Record it rather than panicking about it.</p>
<p><strong>Record:</strong> the list of suspicious domains with a note on what each one appears to be.</p>
<h3>31. Anchor text distribution</h3>
<p>Open Links, then Top linking text. Record the breakdown across four buckets: branded (your company name), exact-match commercial phrases, generic ("here", "website", "read more"), and bare URLs. A natural profile is branded-heavy. A profile dominated by exact-match commercial anchors usually means somebody bought links.</p>
<p><strong>Record:</strong> the anchor list with an approximate percentage per bucket.</p>
<h3>32. Link gains and losses</h3>
<p>Search Console shows a snapshot, not a trend, so this check depends on having a previous record. If you have one, compare the referring domain count and the top linking sites list against it and identify anything that has disappeared. If you do not, this audit becomes the baseline. Write the numbers down and date them.</p>
<p><strong>Record:</strong> current referring domain count with today's date, and any domains lost since the last recorded count.</p>
<h3>33. Competitor link gap</h3>
<p>Run your domain and each competitor domain through <a href="https://www.seoptimer.com/">SEOptimer</a> and record the domain strength figure for each. This is a relative indicator, not an absolute measure, and it only means anything when the same tool is used consistently across all the domains. Calculate roughly how far behind or ahead you sit.</p>
<p><strong>Record:</strong> domain strength per domain, and the approximate gap to the strongest competitor.</p>
<hr />
<h2>Section 5: How do you check competitors?</h2>
<p>Four checks, all manual, all done in an incognito window so your own search history does not distort the results.</p>
<h3>34. Identify the top three organic competitors</h3>
<p>Search three to five of your primary non-branded service terms. Note which domains appear in the top five consistently. These are your organic competitors, and they are frequently not your business competitors; directories, marketplaces, and national publishers often occupy the results a local firm is trying to rank in.</p>
<p><strong>Record:</strong> the domains that recur, with the queries each one ranks for.</p>
<h3>35. Compare authority</h3>
<p>Using the domain strength figures from check 33, place your site alongside the three competitors. The point of this number is not accuracy. It is calibration: it tells you whether you are trying to overtake sites in roughly your own weight class or sites with ten years and a thousand referring domains on you.</p>
<p><strong>Record:</strong> the four figures side by side, and which competitors are realistically catchable.</p>
<h3>36. Top pages comparison</h3>
<p>Open each competitor site and map their page inventory: how many service pages, whether they have location pages, whether they have comparison or pricing pages, how much of the site is blog. Compare against your own inventory. Page types you lack entirely are the clearest opportunity in the whole audit.</p>
<p><strong>Record:</strong> a page-type inventory for each competitor and for your own site, with the differences highlighted.</p>
<h3>37. Content depth against competitors</h3>
<p>Take the single query that matters most to you, open the top three ranking pages, and read them. Note what they cover that your equivalent page does not: pricing, process, timelines, objections, FAQs, proof. This is a reading exercise, not a word-count exercise, and it usually produces the most actionable list in the audit.</p>
<p><strong>Record:</strong> per competitor page, the sections and specifics they include that yours omits.</p>
<hr />
<h2>Section 6: How do you check local SEO?</h2>
<p>Skip this section entirely if the business does not serve customers in a defined geographic area. For everyone else, the local layer often produces more revenue per hour of work than anything in section 1.</p>
<h3>38. Google Business Profile</h3>
<p>Open the profile and go through every field: name, primary category, secondary categories, address, service area, hours including holiday hours, phone, website URL, description, services or products, and attributes. Count the photos and note the date of the most recent one. Check whether the primary category matches what you actually want to rank for; this is the single most influential field on the profile.</p>
<p><strong>Record:</strong> completeness field by field, primary and secondary categories, photo count, date of the last post or photo.</p>
<h3>39. NAP consistency</h3>
<p>Find the name, address, and phone number everywhere they appear on your own site: footer, contact page, about page, location pages, and inside any schema markup. Compare them character by character against the Google Business Profile. Variations such as "Street" against "St", a different suite number format, or an old phone number are the finding.</p>
<p><strong>Record:</strong> every on-site instance of NAP with its exact formatting, and each place it differs from the profile.</p>
<h3>40. Local citations</h3>
<p>Run the business name and location through <a href="https://whitespark.ca/local-citation-finder/">Whitespark's free citation finder</a> and note which directories list you. Then search <code>"business name" "city"</code> in Google to catch listings the tool missed. For each listing found, check the NAP matches. For each major directory missing, add it to the action list.</p>
<p><strong>Record:</strong> directories listing you with NAP accuracy noted, and the top five relevant directories where you are absent.</p>
<h3>41. Reviews</h3>
<p>On the Google Business Profile, record the star rating, the total review count, and the date of the most recent review. Then check how many reviews have an owner response. Compare all four figures against the three businesses currently in the local pack for your main service-plus-location query, which is the only comparison that matters.</p>
<p><strong>Record:</strong> rating, count, most recent review date, response rate, and the same four figures for each local pack competitor.</p>
<h3>42. Local schema</h3>
<p>Run the homepage and contact page through the Rich Results Test and look for <code>LocalBusiness</code> markup or one of its subtypes. Check which fields are populated: <code>name</code>, <code>address</code>, <code>telephone</code>, <code>openingHoursSpecification</code>, <code>geo</code>, <code>url</code>, and <code>sameAs</code>. Confirm the values match the NAP recorded in check 39.</p>
<p><strong>Record:</strong> schema type used, fields present, fields missing, and any value that contradicts the site or the profile.</p>
<hr />
<h2>Section 7: How do you check UX and conversion?</h2>
<p>Rankings that do not convert are an expensive hobby. These four checks are quick and they change how you prioritize everything above.</p>
<h3>43. Calls to action on key pages</h3>
<p>Load each key page at a mobile viewport with a clean session. Ask what the single next action is, whether it is visible without scrolling, and whether the button text says what happens next. "Learn more" is not an action. Then count the competing calls to action on the page; three different offers means no offer.</p>
<p><strong>Record:</strong> per key page, the primary action, whether it is above the fold, its exact button text, and the number of competing actions.</p>
<h3>44. Navigation and site structure</h3>
<p>Count the items in the main navigation. Then, from the homepage, count the clicks required to reach each key service page and the contact page. The target is two or fewer. Check the navigation on mobile separately; menus that work on desktop frequently collapse into something unusable on a phone.</p>
<p><strong>Record:</strong> navigation item count, click depth to each key page, and any mobile-specific breakage.</p>
<h3>45. Engagement metrics</h3>
<p>In GA4, go to Reports, Engagement, Pages and screens. For each key page, record the engagement rate and the average engagement time. Note that GA4's engagement rate is the inverse of the old bounce rate; a 40% engagement rate means 60% of sessions were not engaged. Filter to organic traffic only, otherwise direct and branded traffic will flatter the numbers.</p>
<p><strong>Record:</strong> engagement rate and average engagement time per key page, organic sessions only.</p>
<h3>46. Intrusive interstitials</h3>
<p>Load your key landing pages in a mobile viewport in an incognito window, so cookies do not suppress pop-ups. Note anything that appears on load or within the first few seconds and covers the content. A small consent banner is fine. A full-screen overlay served to somebody arriving from search is a problem Google names explicitly in its guidance.</p>
<p><strong>Record:</strong> which pages trigger overlays, what triggers them, the timing, and how much of the viewport they cover.</p>
<hr />
<h2>Section 8: How do you check AI search visibility?</h2>
<p>Search increasingly gets answered before anybody clicks. These six checks establish whether the site is present in generated answers, or whether competitors are supplying them. All of it is manual, and none of it takes long.</p>
<h3>47. Google AI Overview presence</h3>
<p>Take four to six of your most important non-branded queries from check 23 and search each in an incognito window. Note whether an AI Overview block appears at the top of the results. Where it does, expand the citation list and record which domains are being used as sources. The queries where an overview appears and cites only competitors are the priority list.</p>
<p><strong>Record:</strong> per query, whether an overview appears, the cited domains, and whether yours is among them.</p>
<h3>48. Answer engine visibility</h3>
<p>Ask ChatGPT, Perplexity, and Gemini the same three or four buying-intent questions a customer would ask: "who are the best {service} providers in {region}", "recommend a company for {service}". Note whether your brand appears and whether it is linked. Then ask each engine directly, "what is {brand} and what do they do", and check whether the answer is accurate, wrong, or empty. Record which sources each engine cites, because that list is where the visibility is actually being decided.</p>
<p><strong>Record:</strong> per engine, whether the brand surfaces unprompted, whether the direct description is accurate, and the sources cited.</p>
<h3>49. Answer-ready content structure</h3>
<p>Open four or five key pages and check whether each one answers its core question directly in the first paragraph, rather than after three paragraphs of context. Look for the structure engines extract from: descriptive question-shaped H2s, short definitional sentences, tables, and a real FAQ block rather than three questions nobody asked.</p>
<p><strong>Record:</strong> per page, how far down the page the direct answer sits, and whether question headings and an FAQ block exist.</p>
<h3>50. Citation-worthy signals</h3>
<p>Assess whether your pages contain the things generative engines preferentially quote: concrete numbers, prices, timeframes, original data, and clearly sourced claims. Then check for visible authorship: a named author, a credential or bio, and a published or updated date. Content that is anonymous, undated, and free of specifics is not going to be cited by anything.</p>
<p><strong>Record:</strong> per key page, whether an author and date are visible, and how many concrete specifics the page contains.</p>
<h3>51. Answer-supporting structured data</h3>
<p>Run the homepage and two or three key pages through the Rich Results Test and the Schema Markup Validator. Look specifically for <code>Organization</code> with a populated <code>sameAs</code> array, <code>FAQPage</code> on pages with genuine question and answer content, <code>Article</code> with <code>author</code> and <code>datePublished</code> on blog posts, and <code>BreadcrumbList</code>. The <code>sameAs</code> array is the one most often left empty, and it is the link between your site and your profiles elsewhere.</p>
<p><strong>Record:</strong> markup types found per page, missing fields, and the full <code>sameAs</code> list if present.</p>
<h3>52. AI crawler access</h3>
<p>Reopen <code>yourdomain.com/robots.txt</code> and search for these user-agents specifically: <code>GPTBot</code>, <code>OAI-SearchBot</code>, <code>ClaudeBot</code>, <code>PerplexityBot</code>, <code>Google-Extended</code>, <code>CCBot</code>, and <code>Bytespider</code>. Record whether each is allowed, blocked, or unmentioned, then establish whether any block was a deliberate decision or an inherited default from a plugin or a hosting template. Also request <code>yourdomain.com/llms.txt</code> and note the response; absence is a data point, not a fault.</p>
<p><strong>Record:</strong> the directive for each user-agent, whether it was intended, and the llms.txt status code.</p>
<hr />
<h2>FAQ</h2>
<h3>How long does a full website SEO audit take?</h3>
<p>For a small site, four to eight hours for the first pass if you already know the tools, spread across a couple of days because crawls, SSL scans, and PageSpeed runs all involve waiting. The technical and on-page sections take the longest. The AI search section takes under an hour and is usually the most surprising.</p>
<h3>Do I need paid tools to run an SEO audit?</h3>
<p>No. Every check above can be completed with Search Console, PageSpeed Insights, Chrome DevTools, the free Screaming Frog tier, GA4, and free validators. Paid tools save time on sites over 500 URLs and give far better backlink and keyword gap data. They do not reveal a category of problem that free tools miss completely.</p>
<h3>How often should a website be audited?</h3>
<p>A full audit once a year, and after any significant change: a redesign, a platform migration, a CMS upgrade, or a hosting move. Between audits, the Search Console Pages report and Core Web Vitals report are worth a monthly glance, because they surface regressions without you having to go looking for them.</p>
<h3>What is the difference between this and a technical SEO audit?</h3>
<p>A <a href="/technical-seo-audit-checklist/">technical SEO audit</a> covers crawling, rendering, indexation, speed, and security in far more depth, and stops there. This checklist covers the technical layer more briefly, then adds on-page, keywords, backlinks, competitors, local presence, conversion, and AI visibility. Technical is the foundation; this is the whole building.</p>
<h3>Should I fix everything I find?</h3>
<p>No. Most audits produce more findings than any business will act on, which is why severity belongs in the spreadsheet from the start. Fix anything blocking indexation first, then anything on a page that already earns impressions, then everything else. A finding with no traffic behind it can wait.</p>
<hr />
<h2>Closing</h2>
<p>Fifty-two checks produce a document, and the document is the point. Findings with evidence attached can be sequenced, costed, and handed to whoever does the work; impressions cannot. If you would rather have the data gathered and prioritized for you, an <a href="https://illucrum.com/audits/seo-audit/">SEO audit</a> covers all of this, and the implementation can be handled from there.</p>
]]></content:encoded></item><item><title><![CDATA[Local pack and SEO (2026)]]></title><description><![CDATA[SEO for local businesses is an interesting battle, that in a way, is fought on two fronts. On one side is the traditional ranking, and on the other is the local pack. While they are connected, and the]]></description><link>https://blog.illucrum.com/local-pack-and-seo</link><guid isPermaLink="true">https://blog.illucrum.com/local-pack-and-seo</guid><category><![CDATA[SEO]]></category><category><![CDATA[local seo]]></category><category><![CDATA[google business profile]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Tue, 18 Aug 2026 09:27:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/28781bd8-9a69-49c7-837a-20da72e5b69d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>SEO for local businesses is an interesting battle, that in a way, is fought on two fronts. On one side is the traditional ranking, and on the other is the local pack. While they are connected, and the website should stay congruent, the truth is that it's easier to rank on local pack in your city. It is very much possible for your website to stay hidden on the second or third page of regular results, while your Google Business Profile is doing all the job for commercial keywords. This article will focus on that exactly.</p>
<h2>The obvious part</h2>
<p>For your GBP to rank, you first need to have one! And it's not just about having one, it needs some love. Accurate information, few photos, a list of services you offer, etc. Most of this things that if you give it some time and follow the process of creating the profile carefully and with attention to detail, you won't miss. This is the obvious part, which is definitely worth reminding. It's not difficult to have a decent GBP, it just requires a little effort.</p>
<h2>What details need special attention?</h2>
<p>Even though setting up a decent profile is easy and intuitive, there are definitely few thing that are easy to miss. And those things are the opening hours, review recency, review count, review responses and website content.</p>
<h3>Opening hours</h3>
<p>Some businesses, like local shops, don't have much of a choice. They should just write the actual opening hours. There are businesses that can't really afford being found by a user only to frustrate him by being closed while Google states they are open. But there are companies, especially in the legal sector, that close most clients on the phone, for instance. When answering the phone is a priority, some companies even opt to be open 24/7, just to make sure that when they are found, the potential client know he can call right away. Of course this kind of commitment is not for everyone. Still, B2C companies should keep in mind, that if they are closed in the afternoon and on weekends too, they most likely won't receive many phone calls.</p>
<h3>Review recency</h3>
<p>Reviews are probably one of the most important factors. And review recency is especially important to close customers. According to <a href="https://www.brightlocal.com/research/local-consumer-review-survey/">BrightLocal</a>, 18% are only convinced by reviews from within the last seven days. 32% look for reviews two weeks old or less and 74% seek reviews written in the last three months. Getting reviews on Google is not a one time thing. It's not just getting a decent number of reviews with a good overall score. Collecting reviews on Google has to be a constant process, that should never stop.</p>
<h3>Review count</h3>
<p>Once you get the reviews flowing, this is a matter of time. But still worth mentioning. Local pack reviews show not only the overall rating, but also the review count. If you have to choose between three companies you never heard about, they all seem similar, all have good reviews, but one has 200+ reviews, another has only 70+ and the last one has 190+ reviews, which one would you choose? Would you even think about the second one? Placement is of course very important, but so are reviews. And don't forget the overall score is legitimized by their count. 4 stars from hundreds of reviews are more valuable than 5 stars from only a dozen.</p>
<h3>Answering reviews</h3>
<p>This is actually quite similar to any social media. Algorithms nowadays like active users. Also, when your profile is active, it sends a clear signal to the user that the profile is not abandoned, so all the information that can be found in there is up-to-date. So it's definitely answering to the reviews should be a part of the flow.</p>
<h3>Website content</h3>
<p>Another thing to have in mind, is that although local pack is different from normal results, the two are still connected. It's not only about making sure the your online presence remains consistent and congruent. It's also that quite few users actually visits the website of businesses they find. And so it's important that the website supports the GBP, and makes sure the user doesn't go back and choose a competitor.</p>
<hr />
<h2>Conclusion</h2>
<p>A decent GBP is easy to get. Refining it requires a little research, mostly to make sure you are not missing anything. But overall it's a pretty easy and straightforward way of making sure people will get to know about your business. Ranking outside the local pack is still important, and somewhat more difficult to achieve. And so if you need help with SEO or your GBP, check out our <a href="https://illucrum.com/audits/seo-audit/">SEO audit</a> offer.</p>
]]></content:encoded></item><item><title><![CDATA[Technical SEO Checklist]]></title><description><![CDATA[A technical SEO audit answers one question: can search engines find, crawl, render, and index this site without obstruction? It has nothing to do with keywords or content quality. It is infrastructure]]></description><link>https://blog.illucrum.com/technical-seo-checklist</link><guid isPermaLink="true">https://blog.illucrum.com/technical-seo-checklist</guid><category><![CDATA[SEO]]></category><category><![CDATA[technical seo]]></category><category><![CDATA[checklist]]></category><category><![CDATA[guide]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Mon, 27 Jul 2026 08:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/a19c3ad2-338c-4343-aace-6ea988ccd32d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A technical SEO audit answers one question: can search engines find, crawl, render, and index this site without obstruction? It has nothing to do with keywords or content quality. It is infrastructure work.</p>
<p><strong>In short:</strong> A technical SEO audit checks crawlability, indexation, site architecture, JavaScript rendering, speed, mobile experience, security, structured data, and AI crawler access. Most of it can be done with Google Search Console, PageSpeed Insights, Chrome DevTools, and a free crawler.</p>
<hr />
<h2>What you need before you start</h2>
<p>Everything below can be done with free tools. You will need verified access to Google Search Console for the site; without it, roughly a third of the checks are guesswork.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Used for</th>
<th>Cost</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://search.google.com/search-console">Google Search Console</a></td>
<td>Index coverage, crawl stats, URL inspection, Core Web Vitals field data</td>
<td>Free, requires domain verification</td>
</tr>
<tr>
<td><a href="https://pagespeed.web.dev/">PageSpeed Insights</a></td>
<td>Performance scores, Core Web Vitals, render-blocking and image diagnostics</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://developer.chrome.com/docs/devtools/">Chrome DevTools</a></td>
<td>Network tab, console, device emulation, rendered DOM</td>
<td>Free, built into Chrome</td>
</tr>
<tr>
<td><a href="https://www.screamingfrog.co.uk/seo-spider/">Screaming Frog SEO Spider</a></td>
<td>Site crawl, status codes, redirect chains, orphan detection</td>
<td>Free up to 500 URLs</td>
</tr>
<tr>
<td><a href="https://search.google.com/test/rich-results">Google Rich Results Test</a></td>
<td>Structured data validation, rendered HTML view</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://validator.schema.org/">Schema Markup Validator</a></td>
<td>Schema validation beyond Google's rich result types</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://www.ssllabs.com/ssltest/">SSL Labs Server Test</a></td>
<td>Certificate validity, expiry, configuration grade</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://securityheaders.com/">Security Headers</a></td>
<td>HSTS, CSP, and hardening header presence</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://www.seoptimer.com/">SEOptimer</a></td>
<td>Quick crawl summary and domain strength reference</td>
<td>Free tier</td>
</tr>
</tbody></table>
<p>Before you touch anything, create a spreadsheet with four columns: check number, finding, evidence (URL or screenshot), and severity. Fill it as you go.</p>
<hr />
<h2>Section 1: How do you check crawlability and indexation?</h2>
<p>This is the foundation. If crawlers cannot reach pages, or Google has decided not to index them, nothing else in the audit matters.</p>
<h3>1. Robots.txt configuration</h3>
<p>Open <code>yourdomain.com/robots.txt</code> directly in a browser. Confirm it returns HTTP 200, not a 404 or 500. Read the whole file. Look for <code>Disallow: /</code>, which blocks the entire site, and for any rule that catches service pages, the blog, or CSS and JS files needed for rendering. Confirm a <code>Sitemap:</code> directive is present and points to a live sitemap URL.</p>
<p><strong>Record:</strong> status code, full file contents, any Disallow rule affecting content, whether the sitemap is declared.</p>
<h3>2. XML sitemap health</h3>
<p>Open <code>yourdomain.com/sitemap.xml</code>. Confirm it is well-formed XML and returns 200. Take a sample of 15 to 20 listed URLs and check each returns 200, is the canonical version, and is not set to <code>noindex</code>. Confirm the sitemap excludes admin pages, cart pages, thank-you pages, and parameter URLs. Then open Search Console, go to Indexing, then Sitemaps, and compare the discovered URL count against the number of pages you believe the site has.</p>
<p><strong>Record:</strong> URL count in sitemap, number of sampled URLs failing, GSC discovered count, last read date.</p>
<h3>3. Index coverage and excluded pages</h3>
<p>In Search Console, go to Indexing, then Pages. Note the Indexed and Not indexed totals. Open the "Why pages aren't indexed" breakdown and record the count for each reason, paying particular attention to <code>Crawled - currently not indexed</code>, <code>Discovered - currently not indexed</code>, <code>Soft 404</code>, <code>Excluded by noindex tag</code>, and duplicate reasons. Then check that your most commercially important pages appear in the indexed set.</p>
<p><strong>Record:</strong> indexed count, not-indexed count, the full reason breakdown with counts, and any key page found in the not-indexed set.</p>
<h3>4. HTTP status codes and server errors</h3>
<p>Crawl the site with Screaming Frog. Sort the internal URL list by status code. Flag every 4xx and 5xx response that is linked from somewhere on the site or appears in the sitemap. Separately, request a URL that definitely does not exist (<code>yourdomain.com/thispagedoesnotexist</code>) and check the response code in the DevTools Network tab. It must return a true 404. A 404 page returning status 200 is a soft 404 and creates indexable junk.</p>
<p><strong>Record:</strong> list of 4xx URLs with source pages, list of 5xx URLs, and whether the 404 page returns a real 404.</p>
<h3>5. Redirect chains and loops</h3>
<p>In the Screaming Frog crawl, use Reports, then Redirects, then Redirect Chains. A chain is any redirect passing through more than one hop (A to B to C). Also manually test the four host variants and any known legacy URLs. Check whether redirects intended as permanent are 301 rather than 302. Flag any URL that redirects back to itself or into a cycle.</p>
<p><strong>Record:</strong> each chain with its hop count, any 302s used for permanent moves, any loops.</p>
<h3>6. Crawl budget and index bloat</h3>
<p>Compare the total indexed page count from check 3 against the number of pages the site genuinely needs indexed. A large gap is the signal. In Search Console, use the Pages report to list indexed URLs and scan for parameter URLs, filter URLs, tag archives, paginated duplicates, and internal search results pages. Then go to Settings, then Crawl stats, and review what Googlebot is spending requests on by file type and response code.</p>
<p><strong>Record:</strong> indexed count versus intended count, categories of low-value indexed URLs with rough counts, average crawl requests per day.</p>
<h3>7. Orphan pages</h3>
<p>Compare two lists: every URL in the sitemap or your known page inventory, and every URL that Screaming Frog discovered by following internal links. Anything in the first list but not the second is an orphan, reachable only by direct URL or sitemap. Screaming Frog can do this directly if you connect the Search Console API before crawling.</p>
<p><strong>Record:</strong> orphan URL list, flagging any that are commercially important.</p>
<hr />
<h2>Section 2: How do you check site architecture and URLs?</h2>
<h3>8. URL structure and consistency</h3>
<p>Export the URL list from your crawl. Review a representative sample of 30 or so for lowercase-only characters, hyphens rather than underscores or spaces, absence of avoidable dynamic parameters, sensible length, and readable slugs. The thing to look for is inconsistency across page types: some URLs hyphenated and some not, some with trailing slashes and some without.</p>
<p><strong>Record:</strong> the conventions in use per page type, and any mixed conventions.</p>
<h3>9. Canonicalization and duplicate URLs</h3>
<p>On five to ten key pages, view the source and find <code>&lt;link rel="canonical"&gt;</code>. Confirm it exists, uses an absolute HTTPS URL, and points to the page itself. Then test the duplicate access paths: with and without a trailing slash, with a tracking parameter appended, and the print version if one exists. Each should either return the same canonical or redirect.</p>
<p><strong>Record:</strong> per page, whether the canonical is present, self-referencing, and absolute; plus any duplicate path that resolves with 200 and no canonical.</p>
<h3>10. Internal linking and link equity flow</h3>
<p>In the crawl, look at the inlinks count for each page. Check that key commercial pages receive multiple internal links from relevant content, not just from the footer. Sample the anchor text used for those links and note how much of it is "click here", "read more", or the bare URL.</p>
<p><strong>Record:</strong> inlink count for the top ten commercial pages, and a sample of anchor text patterns.</p>
<h3>11. Site depth and click distance</h3>
<p>Screaming Frog reports crawl depth as the number of clicks from the start URL. Sort by depth and look at what sits at level 4 and beyond. The target is important pages within three clicks of the homepage.</p>
<p><strong>Record:</strong> depth distribution (how many URLs at each level), and any commercially important page deeper than three.</p>
<h3>12. Pagination handling</h3>
<p>Find a paginated series such as a blog index or category listing. Open page 2 and view the source. Check that the canonical on page 2 points to page 2, not back to page 1. Check that pagination links are real <code>&lt;a href&gt;</code> elements in the HTML rather than JavaScript-only controls. Check whether paginated pages carry <code>noindex</code>, and whether a "view all" page exists.</p>
<p><strong>Record:</strong> canonical target per paginated page, whether pagination links are crawlable, presence of noindex.</p>
<hr />
<h2>Section 3: How do you check rendering and JavaScript?</h2>
<p>Search engines render JavaScript, but not always immediately and not always completely. The purpose of this section is to establish what exists in the raw HTML versus what only appears after scripts run.</p>
<h3>13. JavaScript rendering and content parity</h3>
<p>Fetch the raw HTML for a key page. In Chrome, "View page source" gives you this, or use <code>curl -s https://yourdomain.com/page</code>. Then open the same page normally and inspect the rendered DOM in DevTools Elements. Compare: is the H1 in the raw HTML? The body copy? The main navigation links? The meta description and canonical? If they only appear in the rendered version, you have a dependency worth documenting. Confirm with the Rich Results Test, which shows you the rendered HTML Google actually produced.</p>
<p><strong>Record:</strong> for each of H1, body content, navigation, canonical, and meta tags, whether it is present in raw HTML, rendered DOM, or both.</p>
<p>If you are not sure whether this affects your own site, an audit will establish it along with everything else worth checking.</p>
<h3>14. Render-blocking resources</h3>
<p>Run the page through PageSpeed Insights. Under Diagnostics, open "Eliminate render-blocking resources" and record the listed files with their estimated savings in milliseconds.</p>
<p><strong>Record:</strong> file list, total potential saving, and the current LCP figure for context.</p>
<h3>15. Lazy-loading of critical content</h3>
<p>Identify the LCP element (PageSpeed names it under "Largest Contentful Paint element"). Then check the HTML for that element. If it is an image carrying <code>loading="lazy"</code>, that is the finding. Also confirm that lazy loading is applied to below-the-fold media rather than blanket-applied to every image.</p>
<p><strong>Record:</strong> the LCP element, whether it is lazy-loaded, and how lazy loading is applied across the page.</p>
<hr />
<h2>Section 4: How do you check speed and Core Web Vitals?</h2>
<h3>16. Page speed, mobile and desktop</h3>
<p>Run the URL through PageSpeed Insights twice, once for each strategy. Record both Performance scores. Score the site against the lower figure, which is almost always mobile. Do this for at least three page types: homepage, a key service or product page, and a content page. A single homepage test is not representative.</p>
<p><strong>Record:</strong> mobile and desktop Performance score per page type, plus the top three listed opportunities.</p>
<h3>17. Core Web Vitals</h3>
<p>From the same PageSpeed report, record LCP, INP, and CLS. Prefer the field data at the top of the report, which comes from real Chrome users, over the lab data below it. If the field data section is absent, the site has insufficient traffic for the Chrome UX Report and you are working with lab data only. Note that. Then check Search Console, Experience, Core Web Vitals for the site-wide picture across URL groups.</p>
<p>Thresholds: LCP at or under 2.5 seconds, INP at or under 200 milliseconds, CLS at or under 0.1.</p>
<p><strong>Record:</strong> the three metric values per page, whether they come from field or lab data, and the count of URLs in each GSC status band.</p>
<h3>18. Image optimization and next-gen formats</h3>
<p>From the PageSpeed report, record the findings under "Properly size images", "Efficiently encode images", "Serve images in next-gen formats", and "Image elements do not have explicit width and height". Then spot-check the hero image in DevTools Network: compare its transferred size and intrinsic dimensions against its rendered display size.</p>
<p><strong>Record:</strong> the four diagnostic values with estimated savings, plus the hero image size comparison.</p>
<h3>19. Caching, compression, and CDN</h3>
<p>Open DevTools, go to Network, reload the page, and click any static asset such as a CSS or JS file. Read the response headers. Look for <code>content-encoding: gzip</code> or <code>br</code>, and a <code>cache-control</code> header with a meaningful <code>max-age</code>. You can do the same from a terminal with <code>curl -I https://yourdomain.com/style.css</code>. Check the asset hostnames and headers for CDN indicators such as <code>cf-ray</code> or <code>x-served-by</code>.</p>
<p><strong>Record:</strong> compression method, cache-control values for static assets, and whether a CDN is in use.</p>
<h3>20. Third-party script weight</h3>
<p>In PageSpeed, open "Reduce the impact of third-party code" and record each third party with its transfer size and main-thread blocking time. Cross-check in DevTools Network by filtering to third-party domains. If a tag manager is installed, open its container and list the tags actually firing.</p>
<p><strong>Record:</strong> third-party list with blocking time, total third-party transfer size, and any script loaded synchronously in the head.</p>
<hr />
<h2>Section 5: How do you check mobile and page experience?</h2>
<h3>21. Mobile responsiveness</h3>
<p>Open DevTools, toggle device emulation, and set the viewport to a common mobile size such as 390 by 844. Load the homepage, a service page, a content page, and any form page. Check for horizontal scroll, content overflowing the viewport, text too small to read without zoom, and broken navigation. Test on a real device if you can; emulation misses touch and font-rendering issues.</p>
<p><strong>Record:</strong> per page type, whether layout holds, plus screenshots of any breakage.</p>
<h3>22. Viewport and tap target sizing</h3>
<p>View the source and confirm <code>&lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;</code> is present and correct. Then, in mobile emulation, inspect the primary navigation links, buttons, and form fields. Google's guidance is a tap target of at least 48 by 48 CSS pixels with 8 pixels of spacing. DevTools shows element dimensions on hover.</p>
<p><strong>Record:</strong> viewport meta content, and a list of interactive elements falling below the size or spacing threshold.</p>
<h3>23. Intrusive interstitials</h3>
<p>Load your key landing pages in mobile emulation with a clean session (use an incognito window so cookies do not suppress pop-ups). Note anything that appears on load or within the first few seconds and covers the main content. Distinguish a small consent banner, which is acceptable, from a full-screen overlay, which is not.</p>
<p><strong>Record:</strong> which pages trigger overlays, what triggers them, timing, and how much of the viewport they cover.</p>
<hr />
<h2>Section 6: How do you check security and HTTPS?</h2>
<h3>24. HTTPS enforcement and SSL certificate</h3>
<p>Confirm the site loads over HTTPS. Then request the HTTP version and check in DevTools Network that it redirects to HTTPS in a single hop. Click the padlock in the address bar to see certificate details: issuer, validity dates, and the domain it covers. Run the domain through <a href="https://www.ssllabs.com/ssltest/">SSL Labs</a> for the configuration grade; the scan takes a couple of minutes.</p>
<p><strong>Record:</strong> redirect behavior and hop count, certificate expiry date, issuer, SSL Labs grade.</p>
<h3>25. Mixed content</h3>
<p>Load key pages with the DevTools Console open. Mixed content warnings appear there automatically. Search the page source for <code>http://</code> references in <code>src</code> and <code>href</code> attributes on images, scripts, stylesheets, and iframes.</p>
<p><strong>Record:</strong> each mixed-content resource with its URL and type, separating active content (scripts, iframes) from passive (images).</p>
<h3>26. Security headers</h3>
<p>Run the domain through <a href="https://securityheaders.com/">securityheaders.com</a>, or read the response headers directly with <code>curl -I https://yourdomain.com</code>. Look for <code>Strict-Transport-Security</code>, <code>X-Content-Type-Options</code>, <code>X-Frame-Options</code> or a frame-ancestors CSP directive, and any Content-Security-Policy.</p>
<p><strong>Record:</strong> which headers are present and their values. This is a hygiene and trust check rather than a ranking factor, so log it and move on.</p>
<h3>27. Exposed sensitive files and endpoints</h3>
<p>Request a set of common paths and note the response codes: <code>/.env</code>, <code>/.git/config</code>, <code>/wp-config.php.bak</code>, <code>/backup/</code>, <code>/admin/</code>, <code>/phpinfo.php</code>, and the staging subdomain if you know one exists. Anything returning 200 with real content is a finding. Then search the page source of key pages for API keys or credentials; press Ctrl+F in view-source and search for <code>key</code>, <code>token</code>, <code>secret</code>, and <code>api</code>.</p>
<p><strong>Record:</strong> each exposed path with its response code, and any credential found in client-side source.</p>
<hr />
<h2>Section 7: How do you check structured data and directives?</h2>
<h3>28. Structured data validity</h3>
<p>Run the homepage and one URL of each significant page type through the <a href="https://search.google.com/test/rich-results">Rich Results Test</a>. Record which schema types are detected, the count of errors, and the count of warnings. Then run the same URLs through the <a href="https://validator.schema.org/">Schema Markup Validator</a>, which validates against schema.org rather than only Google's supported rich result types.</p>
<p><strong>Record:</strong> detected types per page type, errors, warnings, and any page with no structured data at all.</p>
<h3>29. Meta robots directives</h3>
<p>On each key page, view the source and search for <code>&lt;meta name="robots"</code>. Then check the HTTP response headers for <code>X-Robots-Tag</code>, which is easy to miss because it never appears in the HTML. Use the Search Console URL Inspection tool on your top five commercial pages to see the indexability verdict Google itself has reached.</p>
<p><strong>Record:</strong> the robots directive found per page in both locations, and the URL Inspection verdict for key pages.</p>
<h3>30. Open Graph and social meta tags</h3>
<p>View the source on your main page types and record whether <code>og:title</code>, <code>og:description</code>, <code>og:image</code>, <code>og:url</code>, <code>og:type</code>, and the Twitter Card tags are present. Confirm the <code>og:image</code> URL resolves and is at least 1200 by 630 pixels. The <a href="https://developers.facebook.com/tools/debug/">Facebook Sharing Debugger</a> renders the preview and reports missing tags.</p>
<p><strong>Record:</strong> tag presence per template, image dimensions, and any templates sharing an identical og:image.</p>
<h3>31. Hreflang implementation</h3>
<p>If the site is monolingual, mark this N/A and move on. Otherwise, view the source on a page that exists in multiple languages and record the <code>&lt;link rel="alternate" hreflang="..."&gt;</code> set. Check the language and region codes are valid, that each page references itself, that pairs are reciprocal, and that an <code>x-default</code> exists. The <a href="https://technicalseo.com/tools/hreflang/">Merkle hreflang tester</a> validates a URL's tags automatically.</p>
<p><strong>Record:</strong> hreflang set per sampled URL, missing reciprocals, invalid codes, broken target URLs.</p>
<h3>32. WWW, non-WWW, and protocol consistency</h3>
<p>Request all four variants: <code>http://domain.com</code>, <code>http://www.domain.com</code>, <code>https://domain.com</code>, <code>https://www.domain.com</code>. Each should redirect in a single hop to one canonical version. Then confirm that this canonical host is the one used in canonical tags, in the sitemap, and in internal links.</p>
<p><strong>Record:</strong> the final destination and hop count for each of the four variants, plus any variant resolving with 200.</p>
<h3>33. Parameter and faceted URL handling</h3>
<p>Identify the parameter patterns the site generates: sorting, filtering, pagination, tracking, session IDs. Search Console's Pages report will show you which of them Google has indexed. For a sample, view the source and check whether they carry a canonical to the clean URL, a <code>noindex</code>, or nothing at all.</p>
<p><strong>Record:</strong> parameter patterns in use, how many parameter URLs are indexed, and the handling method applied to each pattern.</p>
<hr />
<h2>Section 8: How do you check AI crawler access?</h2>
<h3>34. AI crawler directives</h3>
<p>Reopen <code>yourdomain.com/robots.txt</code> and search specifically for these user-agents: <code>GPTBot</code>, <code>OAI-SearchBot</code>, <code>ClaudeBot</code>, <code>PerplexityBot</code>, <code>Google-Extended</code>, <code>CCBot</code>, and <code>Bytespider</code>. Record whether each is allowed, blocked, or unmentioned. Then establish whether any block was a deliberate decision or an inherited default from a plugin or platform template.</p>
<p><strong>Record:</strong> the directive for each user-agent, and whether the site owner intended it.</p>
<h3>35. llms.txt and machine-readable signals</h3>
<p>Request <code>yourdomain.com/llms.txt</code> and note the response. This is an emerging convention rather than a standard, so absence is not a fault; it is a data point. Separately, check whether core business information (what the company does, pricing, contact details, service descriptions) exists as plain text in the HTML, or whether it is locked inside images, PDFs, or JavaScript-rendered components.</p>
<p><strong>Record:</strong> llms.txt status code, and for each of pricing, contact, and service descriptions, whether the information is plain-text accessible.</p>
<h3>36. Entity structured data</h3>
<p>Run the homepage through the Rich Results Test and the Schema Markup Validator. Look specifically for <code>Organization</code> or <code>LocalBusiness</code> markup and record which fields are populated: <code>name</code>, <code>url</code>, <code>logo</code>, <code>description</code>, and <code>sameAs</code>. The <code>sameAs</code> array should list the brand's profiles on LinkedIn, review platforms, and social networks.</p>
<p><strong>Record:</strong> entity type used, fields present, and the full sameAs list.</p>
<hr />
<h2>FAQ</h2>
<h3>How long does a technical SEO audit take?</h3>
<p>For a small site, the first full pass takes four to six hours if you know the tools. Most of that is waiting: crawls, SSL Labs scans, and PageSpeed runs across multiple page types. Larger sites take longer mainly because sampling has to be more careful, not because the checks change.</p>
<h3>Do I need paid tools for a technical SEO audit?</h3>
<p>No. Every check in this list can be completed with Search Console, PageSpeed Insights, Chrome DevTools, the free Screaming Frog tier, and a handful of free validators. Paid crawlers save time on sites above 500 URLs and give better internal link analysis, but they do not surface a category of problem that free tools miss entirely.</p>
<h3>How often should a technical audit be repeated?</h3>
<p>After any significant change: a redesign, a platform migration, a CMS upgrade, or a hosting move. Search Console Pages report and Core Web Vitals report are worth checking regularly, since they surface regressions without you having to look for them.</p>
<h3>What is the difference between a technical audit and a full SEO audit?</h3>
<p>A technical audit covers crawling, rendering, indexation, speed, and security. A full audit adds on-page content, keyword performance, backlink profile, competitor comparison, and conversion factors. Technical is the foundation layer; the rest depends on it working. Running a content audit on a site that Google cannot crawl properly wastes the effort.</p>
<hr />
<h2>Closing</h2>
<p>The value of a technical audit is in the record, not the reading. Thirty-six measured findings, each with evidence attached, give you something to sequence and hand to a developer. Thirty-six impressions do not. If you would rather have the data collected and prioritized for you, a <a href="https://illucrum.com/audits/technical-seo-audit/">technical SEO audit</a> covers all of it, and the implementation can be handled from there.</p>
]]></content:encoded></item><item><title><![CDATA[Technical SEO Audit vs Full SEO Audit ]]></title><description><![CDATA[You are shopping for an audit and you see two options. One is cheaper and called a "technical SEO audit." The other costs more and gets labelled "full," "comprehensive," or just "SEO audit." They soun]]></description><link>https://blog.illucrum.com/technical-seo-audit-vs-full-seo-audit</link><guid isPermaLink="true">https://blog.illucrum.com/technical-seo-audit-vs-full-seo-audit</guid><category><![CDATA[SEO]]></category><category><![CDATA[technical seo]]></category><category><![CDATA[SEO audit]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Tue, 16 Jun 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/8068fdd4-3d6f-427b-94cb-f7aad578a35f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You are shopping for an audit and you see two options. One is cheaper and called a "technical SEO audit." The other costs more and gets labelled "full," "comprehensive," or just "SEO audit." They sound like the same thing in two sizes. They are not, and buying the wrong one wastes money while leaving the real problem untouched.</p>
<p>This article explains what each audit covers, where they overlap, and how to tell which one your site actually needs. No jargon left undefined, and no pressure to buy the bigger package if the smaller one solves your problem.</p>
<p><strong>In short:</strong> A technical SEO audit checks whether search engines can crawl, render, and index your site. A full SEO audit covers all of that, plus content, keywords, backlinks, competitors, and conversions. Technical is one slice of the full audit. If a hidden infrastructure fault is hurting you, technical is enough; if you want to know why you are not ranking, you need the full picture.</p>
<h2>What is a technical SEO audit?</h2>
<p>A technical SEO audit checks the machinery underneath your website. Not the words on the page, but whether search engines can reach those words, read them, and file them correctly. If that machinery is broken, the rest of your SEO effort is wasted, because the page never makes it into the search index in the first place.</p>
<p>Most technical audits look at the same core areas.</p>
<p><strong>Crawlability.</strong> Whether search engine bots can move through your site and reach every page that matters. This covers your robots.txt file (the file that tells bots where they may and may not go), your XML sitemap, broken links, and redirect chains that send bots in circles.</p>
<p><strong>Indexation.</strong> Whether the pages bots reach actually end up in Google's index. A single stray "noindex" tag can quietly remove an important page from search. Duplicate content and misconfigured canonical tags (the signal that tells Google which version of a page is the original) also sit here.</p>
<p><strong>Speed and Core Web Vitals.</strong> How quickly pages load and respond. Google measures three things it calls Core Web Vitals: Largest Contentful Paint (loading, target under 2.5 seconds), Interaction to Next Paint (responsiveness, target under 200 milliseconds), and Cumulative Layout Shift (visual stability, target under 0.1). These are confirmed ranking signals, and they affect conversions too.</p>
<p><strong>Mobile and security.</strong> Google indexes the mobile version of your site, not the desktop one, so the mobile experience has to carry all the same content. HTTPS, the secure version of a web connection, is a confirmed ranking factor and a basic trust signal.</p>
<p><strong>Structured data and architecture.</strong> Schema markup (code that tells search engines what a page is about) and a logical internal linking structure help both search engines and, increasingly, AI systems understand and surface your content.</p>
<p>The goal of all this is narrow and important: make sure search engines can find, read, and trust your site. A technical audit does not tell you whether you are targeting the right keywords or whether your content is any good. It tells you whether the plumbing works.</p>
<h2>What does a full SEO audit cover?</h2>
<p>A full SEO audit includes everything above, then keeps going. It treats technical health as the foundation rather than the whole building, and it examines the factors that decide whether a technically sound site actually ranks and earns leads.</p>
<p>The areas a full audit adds:</p>
<ul>
<li><p><strong>On-page SEO:</strong> titles, meta descriptions, heading structure, and how well each page is optimised for the term it should rank for.</p>
</li>
<li><p><strong>Content and keywords:</strong> whether you are targeting terms people actually search, where the gaps are, and whether two pages are competing for the same keyword (a problem called keyword cannibalisation).</p>
</li>
<li><p><strong>Backlinks and authority:</strong> the quality and profile of sites linking to you, since links remain one of the strongest signals of trust.</p>
</li>
<li><p><strong>Competitor analysis:</strong> what the sites outranking you are doing differently, and where the realistic openings are.</p>
</li>
<li><p><strong>Local SEO:</strong> for businesses serving a geographic area, the Google Business Profile, citations, and reviews that drive local visibility.</p>
</li>
<li><p><strong>UX and conversion:</strong> whether the traffic you do earn turns into enquiries, or leaks away on a confusing page.</p>
</li>
</ul>
<p>The output is different too. A good full audit does not just list problems; it ranks them by impact and ties them to business outcomes, so you know which three fixes to make first instead of drowning in a hundred minor warnings.</p>
<h2>Technical SEO audit vs full SEO audit: the key differences</h2>
<p>The clearest way to see the gap is side by side.</p>
<table>
<thead>
<tr>
<th></th>
<th>Technical SEO audit</th>
<th>Full SEO audit</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Main question</strong></td>
<td>Can search engines use my site?</td>
<td>Why does my site rank where it does, and how do I improve it?</td>
</tr>
<tr>
<td><strong>Scope</strong></td>
<td>Crawling, indexing, speed, mobile, security, schema</td>
<td>Technical, plus content, keywords, backlinks, competitors, local, conversion</td>
</tr>
<tr>
<td><strong>Best when</strong></td>
<td>You suspect an infrastructure fault</td>
<td>You want a complete picture and a growth plan</td>
</tr>
<tr>
<td><strong>Typical output</strong></td>
<td>A list of technical fixes</td>
<td>A prioritised roadmap tied to traffic and revenue</td>
</tr>
<tr>
<td><strong>Cost and time</strong></td>
<td>Lower, faster</td>
<td>Higher, more thorough</td>
</tr>
<tr>
<td><strong>What it misses</strong></td>
<td>Strategy, content, competition</td>
<td>Little, if done properly</td>
</tr>
</tbody></table>
<p>The table makes the relationship plain. A technical audit is a subset of a full audit, not a competing product. The question is never which is better; it is which scope matches the problem you are trying to solve.</p>
<h2>Which audit does your site actually need?</h2>
<p>Start with the symptom.</p>
<p>If your traffic dropped suddenly, you recently migrated to a new domain or platform, or you just launched a redesign, a technical audit is the right first move. Sudden changes usually break something mechanical: a sitemap, a redirect, an accidental noindex tag rolled out across a template. A focused technical pass finds those fast, and they are often cheap to fix once identified.</p>
<p>If your site works fine but has plateaued, if you are new to SEO and want to know where you stand, or if you operate in a competitive market and cannot understand why rivals outrank you, a full audit is the better spend. Those problems rarely come from the plumbing. They come from content that is not competitive, keywords nobody searches, or an authority gap that no amount of technical tidying will close.</p>
<p>There is an honest limit worth stating plainly. A technical audit can hand your site a clean bill of health and you can still rank nowhere. Technical SEO gets you found; it does not get you chosen. Being crawlable and fast is the price of entry, not the thing that wins. If you are not sure which camp your site falls into, a full audit surfaces the technical issues and the content and authority gaps in one pass, then ranks them by what actually moves traffic.</p>
<h2>The catch: an audit is only as good as its priorities</h2>
<p>There is a version of the technical audit that is close to worthless, and it is the one most commonly sold cheaply. You pay a small fee, a tool crawls your site, and you receive a 200-row spreadsheet of "errors" with no sense of which ones matter. Most of them do not. A handful might be costing you real traffic, and the export does nothing to tell you which.</p>
<p>The value in any audit is not the list of issues; it is the judgement applied to them. Knowing that a redirect chain on a forgotten old URL matters far less than a noindex tag sitting on your main service page is the difference between an audit and a data dump. This holds for technical and full audits alike. Before you pay for either, ask one question: does this come with prioritisation, or just findings? Findings are cheap. Knowing what to do first is the part worth paying for.</p>
<h2>Frequently asked questions</h2>
<h3>Is a technical SEO audit enough on its own?</h3>
<p>It depends on the problem. If a mechanical fault is suppressing an otherwise strong site, a technical audit may be all you need. But technical health does not guarantee rankings; it only removes the barriers to them. If your site is technically clean and still not ranking, the answer lies in content, keywords, or authority, none of which a technical audit examines.</p>
<h3>How much does a technical SEO audit cost?</h3>
<p>Prices range widely, from automated tool exports costing very little to detailed manual audits costing several hundred or more. The price usually reflects how much human analysis and prioritisation is involved. A cheap audit often means a raw tool report; a more thorough one should include a person deciding which issues actually matter and in what order to fix them. A fuller breakdown of <a href="https://illucrum.com/pricing">what an SEO audit costs</a> covers the ranges in detail.</p>
<h3>How long does an SEO audit take?</h3>
<p>A focused technical audit on a small site can be done in a day or two. A full audit on a larger or more complex site takes several days, because content, backlinks, and competitor analysis cannot be automated to the same degree. A rushed audit misses the issues that take time to surface, so thoroughness matters more than speed here.</p>
<h3>Do I need a technical audit after a redesign or migration?</h3>
<p>Yes. Redesigns and migrations are the single most common cause of self-inflicted SEO damage. Templates change, URLs move, redirects get missed, and noindex tags meant for the staging site sometimes ship to the live one. A technical audit shortly after launch catches these before they erode rankings that took years to build.</p>
<hr />
<p>The two audits answer different questions. A technical SEO audit asks whether search engines can use your site; a full SEO audit asks why it ranks where it does and what to change. Technical is the foundation, a nice start, not the finish line. If this has raised questions about your own site, our <a href="https://illucrum.com/audits/seo-audit">46-point SEO audit</a> covers the technical layer and the six other areas that decide rankings, with every finding ranked by impact rather than dumped in a list. If you rather only focus on technical SEO, we can do that too with our <a href="https://illucrum.com/audits/technical-seo-audit">technical SEO audit</a>.</p>
]]></content:encoded></item><item><title><![CDATA[When Should a SaaS Startup Actually Start Doing SEO?]]></title><description><![CDATA[A 6-month-old SaaS and a 3-year-old SaaS need completely different SEO strategies. The younger company is still figuring out who its customer is. The older one has proof; it just needs to scale what w]]></description><link>https://blog.illucrum.com/when-to-start-seo-saas-startup</link><guid isPermaLink="true">https://blog.illucrum.com/when-to-start-seo-saas-startup</guid><category><![CDATA[SEO]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[seo for saas startups]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Tue, 09 Jun 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/b3bdcca5-2740-4ca5-8bf4-2d2b5090fea6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A 6-month-old SaaS and a 3-year-old SaaS need completely different SEO strategies. The younger company is still figuring out who its customer is. The older one has proof; it just needs to scale what works. Treating these two situations the same is one of the most common ways founders waste time and money on content that goes nowhere. Here is how to figure out which stage you are actually in, and what SEO should look like for each one.</p>
<p><strong>In short:</strong> The right time to start investing in SEO is immediately after you have validated product-market fit, defined your ICP tightly enough to know what they search for, and have enough runway to wait six to twelve months for organic results. Pre-PMF, focus on foundation-setting, not content production.</p>
<hr />
<h2>Why Timing Matters More Than Most Founders Realise</h2>
<p>SEO is a compounding channel. Results from content you publish today accumulate over months, not days. That compounding is enormously valuable, but it also means that content published at the wrong stage, targeting the wrong audience, compounds in the wrong direction.</p>
<p>If you have not yet validated product-market fit, you do not know which customer you are writing for. You might rank for a cluster of keywords and attract users who churn immediately, which signals poor quality to Google and damages your domain reputation before the right audience ever finds you.</p>
<p>The cost of bad timing is not just wasted effort. It is a handicap you carry into the stages where SEO actually matters.</p>
<hr />
<h2>Stage 1: Pre-PMF (0 to 12 Months, Typically)</h2>
<p>At this stage, your job is not to generate inbound traffic. Your job is to understand whether a product people actually want exists, and to talk to users directly to find out.</p>
<p>SEO is a poor tool for this. The feedback loop is too slow. You need signals in days, not months.</p>
<p>That said, there are two things worth doing now that will pay off later.</p>
<p><strong>Set up your technical foundation.</strong> Make sure your site is indexable, loads quickly, and has clean URL structures. This takes a few hours and prevents problems that are expensive to fix later. A basic <a href="https://illucrum.com/audits/saas-seo-audit">SaaS SEO audit</a> at this stage can surface structural issues before they compound.</p>
<p><strong>Claim and fill your Google Business Profile, if relevant.</strong> Even for SaaS businesses with no local footprint, having a verified presence matters for branded search trust.</p>
<p>Do not write content yet. You do not know what to write. Wait until you know who you are writing for.</p>
<hr />
<h2>Stage 2: Post-PMF, Pre-Scale (Typically 12 to 36 Months)</h2>
<p>This is the moment most SaaS founders miss. They either jump into aggressive content production before their ICP is defined, or they delay SEO entirely because they are chasing paid channels.</p>
<p>The right move is to start deliberately, not frantically.</p>
<p>After PMF validation, you should be able to answer these four questions with reasonable confidence:</p>
<ol>
<li><p>Who is your ICP, specifically? Not "small businesses" — which type, which role, which problem.</p>
</li>
<li><p>What words does your ICP use when they search for a solution like yours? Not what you call it; what they call it.</p>
</li>
<li><p>What is your runway? Do you have 18 months to see organic traffic compound, or 9?</p>
</li>
<li><p>Can you commit to consistent output? One piece of quality content per week is more valuable than ten pieces published in a sprint and then nothing.</p>
</li>
</ol>
<p>If you can answer all four clearly, you are ready to start building your SEO programme. If you cannot answer question one or two, pause and do the ICP research first. Everything downstream depends on it.</p>
<hr />
<h2>The Pre-Scale SEO Checklist for SaaS Founders</h2>
<p>Before you commission your first content brief or hire a content writer, work through this checklist:</p>
<ul>
<li><p>[ ] PMF is validated: you have paying customers who came back, referred others, or renewed</p>
</li>
<li><p>[ ] ICP is defined: you know the job title, company size, industry, and core pain of the buyer</p>
</li>
<li><p>[ ] You have mapped at least one keyword cluster your ICP uses when searching for your category</p>
</li>
<li><p>[ ] Technical SEO basics are in place: fast load times, no crawl errors, clean site structure</p>
</li>
<li><p>[ ] You have a blog or resources section that is indexed and ready to receive content</p>
</li>
<li><p>[ ] You have at least 6 months of runway beyond your current burn rate (SEO takes time)</p>
</li>
<li><p>[ ] You have one person, internal or external, who owns the SEO workflow</p>
</li>
</ul>
<p>If more than two of these are unchecked, focus there before producing content.</p>
<hr />
<h2>What a 6-Month-Old SaaS Should Actually Do</h2>
<p>Assume you are six months in. You have paying customers, early signs of retention, and a clearer picture of your buyer. Here is where to spend your SEO time:</p>
<p><strong>Keyword research focused on problem-aware terms.</strong> Your ICP at this stage is likely not searching for your product category by name. They are searching for their problem. "How to reduce churn for B2B SaaS" is a problem-aware query. "Customer success software" is a solution-aware query. Both matter, but problem-aware content builds pipeline earlier.</p>
<p><strong>One cornerstone article per quarter, not one per week.</strong> A well-researched 2,000-word article that targets a real query your ICP has is worth more than six thin posts. Depth signals expertise; expertise builds trust; trust earns links.</p>
<p><strong>Build the internal link structure from day one.</strong> Every article should link to at least one pillar page on your site. Pillar pages link to cluster articles. This architecture tells Google which pages matter most and accelerates ranking for your most commercial terms.</p>
<p><strong>Do not pursue backlinks aggressively at this stage.</strong> Backlinks matter eventually, but at six months, your content is not yet strong enough to earn links at scale. Focus on creating content worth linking to; the links follow.</p>
<hr />
<h2>What a 3-Year-Old SaaS Should Do Differently</h2>
<p>By year three, the game has shifted. You have content assets, some domain authority, and probably a better picture of what is already ranking. Now the work looks different:</p>
<p><strong>Audit before adding.</strong> Before publishing anything new, understand what you already have. Which pages are getting impressions but not clicks? Which ones rank on page two and could be pushed to page one with a content refresh? Adding more content to a weak foundation is like pouring water into a leaky bucket.</p>
<p><strong>Target commercial-intent terms more aggressively.</strong> Your ICP at this stage has likely heard of your category. They are searching "[your category] best tools" or "[competitor] alternative." These terms convert at higher rates and should be prioritised over purely informational content.</p>
<p><strong>Invest in conversion rate optimisation alongside SEO.</strong> Traffic that does not convert is a cost, not an asset. By year three, if organic traffic is growing but trial signups are flat, the problem is probably the page, not the keyword.</p>
<p><strong>Build or commission competitor comparison pages.</strong> Searches like "[Competitor] vs [Your Product]" have high commercial intent and are often easier to rank for than generic category terms. These pages also serve your sales team as objection-handling assets.</p>
<hr />
<h2>DIY SEO or Hire Someone? The Honest Answer</h2>
<p>At the pre-PMF and early post-PMF stages, DIY SEO is often the right call. You cannot brief an agency or freelancer to write for an ICP you have not yet defined. And the foundation-setting work, technical basics, keyword research, site structure, can be done without specialist help if you are willing to learn.</p>
<p>The case for bringing in external expertise gets stronger once you have content producing results. At that point, you need someone who can interpret the data, identify gaps, and build on what works, rather than start from scratch.</p>
<p>A productised audit at this stage gives you a clear picture of where you stand before you commit ongoing spend. That is a better use of budget than months of retainer work on a site that has unresolved structural problems.</p>
<hr />
<h2>FAQ</h2>
<h3>How long does it take to see results from SEO for a SaaS?</h3>
<p>For a new domain with no existing authority, expect six to twelve months before meaningful organic traffic arrives. In competitive categories, eighteen months is realistic. The timeline shortens significantly if you are targeting long-tail, low-competition keywords first and building domain authority steadily through quality content and genuine backlinks.</p>
<h3>Should a SaaS startup use paid ads instead of SEO?</h3>
<p>Paid and organic serve different roles. Paid delivers immediate traffic with immediate cost; organic delivers compounding traffic with delayed payoff. Early-stage companies often need paid for rapid validation and cash flow, but relying on paid only leaves you exposed to rising CPCs over time. The strongest SaaS companies build both channels, with SEO maturing as the business scales.</p>
<h3>What is the biggest SEO mistake early-stage SaaS founders make?</h3>
<p>Writing content before the ICP is defined. The second biggest is targeting high-volume keywords that are too competitive for a new domain. Both mistakes produce content that ranks for nothing or attracts the wrong traffic. Start narrow, go deep, and expand once you have traction.</p>
<h3>Is SaaS SEO different from traditional SEO?</h3>
<p>The core mechanics are the same, but the content strategy differs significantly. SaaS buyers move through longer consideration cycles, research more thoroughly, and rely on comparison content, integration guides, and ROI justification in ways that product or local businesses do not. The keyword clusters you target and the content formats that convert are different as a result.</p>
<h3>What does a SaaS SEO audit actually cover?</h3>
<p>A good audit covers technical site health, on-page optimisation, keyword mapping against your ICP, internal link structure, backlink profile, and competitor gap analysis. The goal is not a list of problems to fix; it is a prioritised action plan tied to business outcomes.</p>
<hr />
<p>The decision of when to start SEO for your SaaS is not really about timing. It is about readiness. Build the foundation early, wait for PMF confirmation before scaling content, and make sure your ICP is defined precisely enough that you know what to write and for whom. If you want an outside view of where your site stands before committing to an ongoing strategy, an <a href="https://illucrum.com/audits/saas-seo-audit">SEO audit for SaaS</a> is the logical starting point.</p>
]]></content:encoded></item><item><title><![CDATA[SaaS SEO Checklist (2026)]]></title><description><![CDATA[A SaaS site has a different SEO surface area from a brochure site. It has an app on a subdomain that should never be indexed, a pricing page that decides half your organic revenue, a features section ]]></description><link>https://blog.illucrum.com/saas-seo-checklist</link><guid isPermaLink="true">https://blog.illucrum.com/saas-seo-checklist</guid><category><![CDATA[SaaS]]></category><category><![CDATA[Seo For Saas,]]></category><category><![CDATA[seo checklist]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Tue, 12 May 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/2691c3ec-f984-4767-9a51-d59b3858a3a5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p>A SaaS site has a different SEO surface area from a brochure site. It has an app on a subdomain that should never be indexed, a pricing page that decides half your organic revenue, a features section that is usually one page when it should be twelve, and a trial flow at the end that quietly wastes every ranking you earn. This SaaS SEO audit checklist works through all of it, in the order it makes sense to look.</p>
<p><strong>In short:</strong> A SaaS SEO audit covers rendering and app subdomain handling, pricing and feature page structure, funnel-stage keyword coverage, comparison and integration content, trial flow friction, review platform footprint, and AI search visibility. All 52 checks below can be run with free tools.</p>
<hr />
<h2>What do you need before you start?</h2>
<p>Everything here runs on free tools, but two things gate the audit. Without verified Google Search Console access you cannot complete the keyword and indexation checks, which is a third of the value. Without knowing your own product's integration list and buyer personas, section 5 is guesswork.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Used for</th>
<th>Cost</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://search.google.com/search-console">Google Search Console</a></td>
<td>Index coverage, queries by funnel stage, positions, links</td>
<td>Free, requires domain verification</td>
</tr>
<tr>
<td><a href="https://pagespeed.web.dev/">PageSpeed Insights</a></td>
<td>Performance scores, Core Web Vitals, JavaScript bundle diagnostics</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://developer.chrome.com/docs/devtools/">Chrome DevTools</a></td>
<td>Raw source versus rendered DOM, network, device emulation</td>
<td>Free, built into Chrome</td>
</tr>
<tr>
<td><a href="https://www.screamingfrog.co.uk/seo-spider/">Screaming Frog SEO Spider</a></td>
<td>Crawl, status codes, titles, canonical tags, orphan detection</td>
<td>Free up to 500 URLs</td>
</tr>
<tr>
<td><a href="https://search.google.com/test/rich-results">Google Rich Results Test</a></td>
<td>Structured data validation and the rendered HTML Google produced</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://validator.schema.org/">Schema Markup Validator</a></td>
<td>Schema validation beyond Google's rich result types</td>
<td>Free</td>
</tr>
<tr>
<td><a href="https://www.g2.com/">G2</a> and <a href="https://www.capterra.com/">Capterra</a></td>
<td>Review volume, recency, category placement against competitors</td>
<td>Free to view</td>
</tr>
<tr>
<td>ChatGPT, <a href="https://www.perplexity.ai/">Perplexity</a>, Gemini</td>
<td>Whether the product is recommended in generated answers</td>
<td>Free tiers</td>
</tr>
<tr>
<td><a href="https://analytics.google.com/">Google Analytics 4</a></td>
<td>Engagement rate and time on commercial pages, organic segment</td>
<td>Free, requires property access</td>
</tr>
<tr>
<td><a href="https://www.seoptimer.com/">SEOptimer</a></td>
<td>Quick crawl summary and domain strength reference</td>
<td>Free tier</td>
</tr>
</tbody></table>
<p>Open a spreadsheet first. Four columns: check number, finding, evidence, severity. Then pick the sample pages you will use throughout and do not change them: homepage, pricing page, one feature page, one integration or use-case page if either exists, the trial or demo page, and one blog post.</p>
<p>One SaaS-specific note before you start. Decide early whether the marketing site and the app live on the same host, a subdomain, or a separate domain, and write it down. Half the technical findings below depend on knowing which is which.</p>
<hr />
<h2>Section 1: How do you check technical SEO on a SaaS site?</h2>
<p>The generic technical checks apply, but three things break more often on SaaS sites than anywhere else: client-side rendering, app subdomain handling, and the documentation subdomain.</p>
<h3>1. Page speed, mobile and desktop</h3>
<p>Run each sample page through PageSpeed Insights on both strategies. Record both Performance scores and judge on the mobile figure. Marketing sites built on React or Next.js frequently ship a JavaScript bundle sized for an application rather than a landing page, so check the "Reduce unused JavaScript" and "Reduce JavaScript execution time" diagnostics specifically.</p>
<p><strong>Record:</strong> mobile and desktop score per page, plus unused JavaScript and execution time figures.</p>
<h3>2. Core Web Vitals</h3>
<p>From the same reports, record LCP, INP, and CLS. Use the field data at the top of the report, drawn from real Chrome users, in preference to the lab data below it. If there is no field section, the site lacks the traffic to appear in the Chrome UX Report; note that and treat the lab numbers as indicative. Pay particular attention to CLS on the pricing page, where a late-loading plan table shifts content at the exact moment somebody is deciding.</p>
<p>Thresholds: LCP at or under 2.5 seconds, INP at or under 200 milliseconds, CLS at or under 0.1.</p>
<p><strong>Record:</strong> the three values per page, field or lab, and the Search Console Core Web Vitals status bands.</p>
<h3>3. HTTPS and SSL certificate</h3>
<p>Confirm HTTPS is enforced and that HTTP redirects in a single hop. Check the certificate issuer, coverage, and expiry via the padlock, then run the domain through <a href="https://www.ssllabs.com/ssltest/">SSL Labs</a>. Check the app subdomain separately; it frequently has a different certificate and a different configuration from the marketing site.</p>
<p><strong>Record:</strong> redirect behavior and hop count, certificate expiry and issuer for both marketing and app hosts, SSL Labs grade.</p>
<h3>4. Mobile responsiveness of commercial pages</h3>
<p>In DevTools device emulation at 390 by 844, load the pricing page, a feature page, and the trial page. Pricing tables are the usual failure: three or four plan columns that either overflow horizontally or collapse into an order that puts the wrong plan first. Check that plan comparison remains possible, that the trial CTA is reachable without pinch-zooming, and that form fields are usable.</p>
<p><strong>Record:</strong> per commercial page, whether the layout holds, how the pricing table degrades, and screenshots of any breakage.</p>
<h3>5. JavaScript rendering and content parity</h3>
<p>This is the highest-value check on a SaaS site. Fetch the raw HTML for the homepage and a feature page, either through "View page source" or <code>curl -s https://yourdomain.com/page</code>. Then inspect the rendered DOM in DevTools Elements. Compare: is the H1 in the raw HTML? The body copy? The navigation links? The canonical and meta description? Confirm with the Rich Results Test, which shows the rendered HTML Google actually produced.</p>
<p><strong>Record:</strong> for each of H1, body copy, navigation links, canonical, and meta tags, whether it appears in raw HTML, rendered DOM, or both.</p>
<h3>6. Robots.txt and XML sitemap</h3>
<p>Open <code>yourdomain.com/robots.txt</code> and read the whole file, then do the same for the app and docs subdomains, each of which has its own. Look for rules that block feature, integration, or pricing paths. Then open the sitemap, confirm it is valid XML, sample 15 to 20 URLs for 200 status and canonical form, and confirm no app or login URLs are listed.</p>
<p><strong>Record:</strong> robots.txt contents per host, any rule affecting marketing pages, sitemap URL count, sampled URL failures, and any app URL found in the sitemap.</p>
<h3>7. App subdomain handling</h3>
<p>Establish where the application lives and what happens when a crawler reaches it. Request the app root and a logged-out dashboard URL and record the status code and any <code>noindex</code> directive. Then search <code>site:app.yourdomain.com</code> in Google and count the indexed results. Zero is the target. Anything above zero is login walls and empty states appearing in search under your brand.</p>
<p><strong>Record:</strong> app host, status codes and robots directives for logged-out app URLs, and the <code>site:</code> indexed count.</p>
<h3>8. Canonical tags and duplicate URLs</h3>
<p>On each sample page, view the source and confirm a self-referencing absolute HTTPS canonical. Then test the SaaS-specific duplicate paths: the same page with a UTM parameter appended, with and without a trailing slash, and any page that exists under two routes (for example <code>/features/reporting</code> and <code>/product/reporting</code>). Each variant should carry the canonical of the original.</p>
<p><strong>Record:</strong> per page, whether the canonical is present, self-referencing, and absolute; plus any duplicate route returning 200 with no canonical.</p>
<h3>9. Structured data</h3>
<p>Run the homepage, pricing page, and a feature page through the <a href="https://search.google.com/test/rich-results">Rich Results Test</a> and the <a href="https://validator.schema.org/">Schema Markup Validator</a>. Record which types are detected. For SaaS the relevant set is <code>SoftwareApplication</code> or <code>Product</code>, <code>Organization</code>, <code>FAQPage</code> where genuine Q and A exists, <code>BreadcrumbList</code>, and <code>Article</code> on blog content.</p>
<p><strong>Record:</strong> types detected per page type, error and warning counts, and any commercial page with no structured data at all.</p>
<h3>10. Indexation health</h3>
<p>In Search Console, go to Indexing, then Pages. Record indexed and not-indexed totals, then open the reason breakdown. On SaaS sites the reasons that matter most are <code>Crawled - currently not indexed</code> on thin feature or integration pages, and <code>Duplicate without user-selected canonical</code> on parameterized URLs. Confirm that pricing, every feature page, and the trial page appear in the indexed set.</p>
<p><strong>Record:</strong> indexed and not-indexed counts, the full reason breakdown, and the index status of every commercial page individually.</p>
<hr />
<h2>Section 2: How do you check on-page SEO across the funnel?</h2>
<p>SaaS on-page problems are rarely about tags being missing. They are about pages that read as brand positioning when the query behind them is a product search.</p>
<h3>11. Title tags</h3>
<p>Export the title column from your crawl. Check for missing and duplicate titles first, then read them. The two SaaS-specific failures are feature pages titled "{Product} | Features" rather than naming the capability, and a pricing page whose title does not contain the word "pricing", which is the exact term people search.</p>
<p><strong>Record:</strong> missing and duplicate titles, every feature page title that does not name its feature, and whether the pricing title contains "pricing".</p>
<h3>12. Meta descriptions</h3>
<p>Export the descriptions and check the commercial pages only. Google rewrites the majority of meta descriptions and the tag is not a ranking factor, so this is a click-through exercise, not a site-wide project. Write them properly for pricing, trial, comparison, and top feature pages, where the description functions as ad copy for a decision-stage searcher.</p>
<p><strong>Record:</strong> missing or duplicated descriptions on commercial pages, and whether each says something specific rather than restating the brand tagline.</p>
<h3>13. Heading structure</h3>
<p>Check each sample page has exactly one H1, that headings descend in order, and that the H2s read as an outline. On feature pages, the H2s should name capabilities, not stages of a story; "Real-time reporting" is a heading, "How it works" is a placeholder. On the pricing page, plan names should sit in headings rather than in styled divs.</p>
<p><strong>Record:</strong> pages with no H1 or multiple H1s, hierarchy breaks, and the H2 outline for each commercial page.</p>
<h3>14. Homepage positioning and the H1</h3>
<p>Read the homepage H1 on its own and ask what category of software it describes. "Work better, together" describes nothing. "Project management software for remote teams" describes a category, a use case, and a buyer. Then check whether the ideal customer is named anywhere above the fold. This is the check that most often explains why a product ranks for its brand name and nothing else.</p>
<p><strong>Record:</strong> the exact H1 text, whether it contains a category term, and whether the target customer is named above the fold.</p>
<h3>15. Pricing page SEO</h3>
<p>Confirm the pricing page exists, returns 200, and is not <code>noindex</code>. Check the title and H1 for the word "pricing". Then check whether prices are actually published as text, or hidden behind "Contact sales" or locked inside an image. Published pricing ranks for a decision-stage query and gets quoted by AI answers; hidden pricing forfeits both.</p>
<p><strong>Record:</strong> indexability, title and H1 wording, whether prices are plain text, plan names present, and whether an FAQ block exists.</p>
<h3>16. Feature page architecture</h3>
<p>Map how features are presented. Does each core capability have its own URL, its own title, its own H1, and body copy describing it, or are twelve features listed on a single <code>/features</code> page? One page cannot rank for twelve distinct capability queries. Count how many features the product has and how many have a dedicated indexable page.</p>
<p><strong>Record:</strong> total core features, number with a dedicated URL, and the list of features with no page of their own.</p>
<h3>17. Content depth on commercial pages</h3>
<p>Read the feature and use-case pages as a buyer evaluating three products in a browser with three tabs open. Ask whether the page explains what the feature does, who it is for, what it replaces, and what its limits are. Marketing copy that says "powerful", "flexible", and "intuitive" without a single specific is the finding. Word count is a symptom here, not a target.</p>
<p><strong>Record:</strong> per commercial page, a one-line completeness judgement and the questions it fails to answer.</p>
<h3>18. Internal linking</h3>
<p>In the crawl, check the inlink count for pricing, each feature page, and the trial page. Then check the direction of flow: do blog posts link to the feature pages they are topically about, or do they all link to the homepage? Do feature pages link to each other and to the trial? Run the orphan report to find feature or integration pages nothing points at.</p>
<p><strong>Record:</strong> inlink counts for commercial pages, whether blog content links to features, and the orphan list.</p>
<p>If working through this on your own product is more time than you want to spend, a <a href="https://illucrum.com/audits/saas-seo-audit/">SaaS SEO audit</a> covers the same ground and arrives prioritized.</p>
<hr />
<h2>Section 3: How do you check funnel keyword coverage?</h2>
<p>SaaS buyers move through three distinct search modes, and most products are visible in only one of them. This section establishes which.</p>
<h3>19. Funnel stage keyword coverage</h3>
<p>In Search Console, go to Performance, Search results, set the range to three months, and export all queries. Then bucket them into three groups: awareness ("{category} software", "how to {outcome}"), consideration ("best {category} tools", "{product} vs {competitor}", "{competitor} alternatives"), and decision ("{product} pricing", "{product} review", "{product} free trial"). Count clicks per bucket.</p>
<p><strong>Record:</strong> clicks and impressions per funnel stage, and which stage is thinnest.</p>
<h3>20. Comparison and "best of" visibility</h3>
<p>Search "best {category} software", "{product} vs {top competitor}", and "{top competitor} alternatives" in an incognito window. Record what ranks: your pages, competitor pages, or review platforms and listicles. Then check whether your site has a page targeting each of those query shapes at all. Most products discover here that they have no comparison content and are ceding the highest-intent queries in the category entirely.</p>
<p><strong>Record:</strong> per query, the top five results, and whether you have a page targeting it.</p>
<h3>21. Ranking keywords overview</h3>
<p>Back in the Performance report, sort by impressions and read the top 20 queries. Count how many are non-branded and how many of those sit on page one. This is the plainest measure of whether search is acquiring anybody new.</p>
<p><strong>Record:</strong> total clicks, the top 20 queries with position and CTR, and the count of non-branded page-one queries.</p>
<h3>22. Branded versus non-branded split</h3>
<p>Filter queries containing the brand name and record clicks, then invert the filter and record clicks again. Calculate the split. For a SaaS product a heavily branded profile usually means search is functioning as a login shortcut for existing users rather than as an acquisition channel.</p>
<p><strong>Record:</strong> branded clicks, non-branded clicks, and the percentage split.</p>
<h3>23. Keyword mapping and cannibalization</h3>
<p>List your key pages and, for each, write down the single query it is meant to win. Then look for collisions: two feature pages targeting the same capability term, a blog post competing with the feature page it should be feeding, a use-case page overlapping a feature page. Confirm in the Search Console Pages tab, filtering by query to see which URL Google actually chose.</p>
<p><strong>Record:</strong> the page-to-query map, every collision, and which URL Google currently ranks for each contested query.</p>
<h3>24. Keyword placement</h3>
<p>For each commercial page, check whether its intended query appears in the title, the H1, the first paragraph, and at least one H2. This is a coverage check, not a density calculation; density targets stopped meaning anything years ago. What you are looking for is a page that never plainly says what it is.</p>
<p><strong>Record:</strong> per commercial page, the intended query and which of the four positions it occupies.</p>
<h3>25. Search intent alignment</h3>
<p>Take your top 10 non-branded queries and search each in an incognito window. Note the dominant result format: product pages, guides, listicles, review platforms, or Reddit threads. Compare with the page type you have pointed at that query. A feature page competing in a results set made entirely of listicles will not win by being improved; it needs different content pointed at the query.</p>
<p><strong>Record:</strong> per query, the dominant format, your page type, and whether they match.</p>
<hr />
<h2>Section 4: How do you check the trial and demo pages?</h2>
<p>Three checks on the pages where organic traffic either becomes revenue or does not.</p>
<h3>26. Trial, demo, or signup page SEO</h3>
<p>Identify the primary conversion page and confirm it returns 200 and is not <code>noindex</code>. Check whether it targets a query at all; "{product} free trial" and "{product} demo" are real searches with real volume. Read the page as somebody who arrived cold from Google rather than from a nurture email, and ask whether it explains what happens after they click.</p>
<p><strong>Record:</strong> indexability, title and H1, whether the offer is stated plainly, and what the page assumes the visitor already knows.</p>
<h3>27. Trust signals on conversion pages</h3>
<p>Count the trust signals on the pricing and trial pages: customer logos, named testimonials, G2 or Capterra badges with a real rating, security and compliance marks such as SOC 2 or GDPR, "no credit card required", and any guarantee. Organic visitors arrive without the warm-up of an ad sequence or a sales call, so these pages carry more of the persuasion load than the team usually assumes.</p>
<p><strong>Record:</strong> the trust signals present on each conversion page, and which of the categories above are absent.</p>
<h3>28. CTA clarity and conversion architecture</h3>
<p>On each key page, identify the single primary action, check it appears above the fold, and read the button text. Then count competing actions. A feature page offering "Start free trial", "Book a demo", "Download the guide", and "Talk to sales" in the same viewport is offering nothing. Check that the action matches the funnel stage: blog posts should not lead with "Talk to sales".</p>
<p><strong>Record:</strong> per page, the primary action, its exact button text, its position, and the number of competing actions.</p>
<hr />
<h2>Section 5: How do you check feature, integration and programmatic pages?</h2>
<p>This is where most SaaS products have the largest untouched keyword surface, and it is usually a structural problem rather than a content problem.</p>
<h3>29. Integration pages</h3>
<p>List every tool your product integrates with. Then check how those integrations are presented: individual pages with their own URL, title, H1, and explanatory copy, or a single <code>/integrations</code> grid of logos. Search "{your product} {integration name}" for three or four of the larger integrations and see whether anything of yours ranks. These queries come from users of the other tool who are actively checking whether you fit their stack.</p>
<p><strong>Record:</strong> total integrations, number with a dedicated indexable page, and ranking status for three sampled integration queries.</p>
<h3>30. Use case and persona pages</h3>
<p>Check whether the site has pages targeting specific buyer types or scenarios: "/for-agencies", "/for-remote-teams", "{category} software for {industry}". Confirm they are genuinely differentiated rather than the homepage with one word swapped, and that they link to the relevant feature pages. Note which of your two or three main personas have no page at all.</p>
<p><strong>Record:</strong> existing use-case and persona pages, how differentiated each is, and the personas with no page.</p>
<h3>31. Programmatic SEO opportunity</h3>
<p>Inventory the repeatable data the product owns: integrations, supported industries, job roles, templates, locations, supported file types. For two or three of these categories, search a sample combination and check whether autocomplete suggests it and whether competitors have built pages for it. Then confirm whether your stack can generate templated pages at all, because a validated opportunity you cannot build is not an opportunity this quarter.</p>
<p><strong>Record:</strong> data categories owned, evidence of demand per category, competitor precedent, and whether the CMS supports templated generation.</p>
<hr />
<h2>Section 6: How do you check content and competitors?</h2>
<p>Seven checks that place the product against the sites actually occupying its results.</p>
<h3>32. Blog and content hub</h3>
<p>Confirm a blog or resource hub exists, count published posts, and note the date of the most recent one. Then check the direction of the links: does blog content point at the feature pages it relates to, or does every post end at the homepage? An abandoned blog is a weaker signal than no blog, because the last-updated date is visible.</p>
<p><strong>Record:</strong> post count, last publish date, publishing frequency over the last six months, and whether posts link to product pages.</p>
<h3>33. Content gap against competitors</h3>
<p>Search 10 to 15 of your target non-branded queries manually and record who ranks. Where a competitor ranks and you are absent, open their page and classify it: guide, comparison, integration page, use-case page, glossary entry, template. The gap is usually a content format you have not built rather than a keyword you have not targeted.</p>
<p><strong>Record:</strong> query-by-query rankings, and the content formats competitors have that you do not.</p>
<h3>34. Identify the top three organic competitors</h3>
<p>Search three to five of your primary non-branded terms in an incognito window and note which domains recur in the top five. Then do the same for "best {category} software". Your organic competitors frequently include G2, Capterra, and a handful of blogs, which are not competitors you can acquire but are results you have to work around.</p>
<p><strong>Record:</strong> recurring domains with the queries each ranks for, separating product competitors from platforms and publishers.</p>
<h3>35. Compare authority</h3>
<p>Run your domain and each product competitor through <a href="https://www.seoptimer.com/">SEOptimer</a> and record the domain strength figure for each. The number is relative and only means anything when the same tool is used across all domains. What you want from it is calibration: whether you are chasing peers or chasing sites with a five-year head start.</p>
<p><strong>Record:</strong> domain strength per domain and the approximate gap to the strongest competitor.</p>
<h3>36. Review platform profiles</h3>
<p>Search your product on <a href="https://www.g2.com/">G2</a>, <a href="https://www.capterra.com/">Capterra</a>, and Product Hunt. For each, check the profile exists and is claimed, the description is complete, the category is correct, and the screenshots are current. Then record the review count and rating, and do the same for your two main competitors. A product with 12 reviews does not get recommended over one with 400, on the platform or by anything reading it.</p>
<p><strong>Record:</strong> per platform, claimed status, completeness, category, review count and rating for you and each competitor.</p>
<h3>37. Competitor content benchmarking</h3>
<p>Open your top two product competitors and count: feature pages, integration pages, use-case pages, comparison pages, and blog posts published in the last six months. Put the numbers next to your own. This produces the clearest single table in the audit and usually explains the ranking difference without further analysis.</p>
<p><strong>Record:</strong> the page-type counts for each competitor and for you, side by side.</p>
<h3>38. SERP feature opportunities</h3>
<p>Search 5 to 10 target queries and note which features appear above the organic results: AI Overview, featured snippet, People Also Ask, video, and review platform listings in the top three. Record which competitor content is winning the snippets and what format it is in.</p>
<p><strong>Record:</strong> per query, the SERP features present, whether you appear in any, and which domain wins each snippet.</p>
<hr />
<h2>Section 7: How do you check the backlink profile?</h2>
<p>Three checks. Search Console is limited compared with a paid backlink tool, but it is accurate about your own domain.</p>
<h3>39. Referring domains</h3>
<p>Go to Links, then Top linking sites. Record the total and scan the top 20, noting what each linking site actually is. For SaaS, the healthy pattern includes review platforms, integration partners' directories, tech press, and newsletters. A count inflated by one syndicated directory listing is not a link profile.</p>
<p><strong>Record:</strong> total linking sites, total external links, and the top 20 domains with a note on each.</p>
<h3>40. Anchor text distribution</h3>
<p>Open Links, then Top linking text. Bucket the anchors into branded, exact-match commercial, generic, and bare URL. A product with organic coverage is branded-heavy, because journalists and partners link with the product name. A profile dominated by exact-match commercial anchors is a bought profile, whether or not the current team bought it.</p>
<p><strong>Record:</strong> the anchor list with an approximate percentage per bucket.</p>
<h3>41. Competitor link gap</h3>
<p>Compare your referring domain count with your two main competitors using the domain strength figures from check 35 and their visible review platform and partner directory presence. Then list the specific link sources they have that you do not: integration partner directories, category listings, tech press coverage, podcast or newsletter mentions.</p>
<p><strong>Record:</strong> the approximate gap, and a named list of link sources competitors hold and you do not.</p>
<hr />
<h2>Section 8: How do you check UX and conversion?</h2>
<p>Rankings that do not convert to trials are a cost center. Five checks, all quick.</p>
<h3>42. Signup and trial flow friction</h3>
<p>Start a trial signup yourself in an incognito window and count the required fields. Note whether a credit card is required before the trial begins, whether social or SSO login is offered, how many steps there are before the product is usable, and whether email verification blocks the first session. Cold organic traffic drops off at each of these in a way that warm traffic does not.</p>
<p><strong>Record:</strong> field count, credit card requirement, login options, step count, and where verification sits in the flow.</p>
<h3>43. Page layout and readability</h3>
<p>Read the feature and pricing pages at mobile width. Look for paragraphs longer than four lines, feature descriptions written as prose where a list would work, and comparison information that cannot be scanned. Buyers scan before they read; a page that requires reading to be understood loses to one that does not.</p>
<p><strong>Record:</strong> per commercial page, the specific sections that are dense or unscannable.</p>
<h3>44. Engagement metrics</h3>
<p>In GA4, go to Reports, Engagement, Pages and screens, and filter to organic traffic only. Record engagement rate and average engagement time for the homepage, pricing page, and top feature pages. Remember GA4's engagement rate is the inverse of the old bounce rate; a 40% engagement rate means 60% of sessions were not engaged.</p>
<p><strong>Record:</strong> engagement rate and average engagement time per commercial page, organic sessions only.</p>
<h3>45. Accessibility basics</h3>
<p>Check the <code>lang</code> attribute on the <code>&lt;html&gt;</code> element, whether form inputs on the signup page have associated labels, whether images carry alt text, and whether the primary CTA colors pass contrast. Beyond the obvious reasons to care, enterprise procurement increasingly asks for a VPAT or an accessibility statement, and finding out during a deal is worse than finding out now.</p>
<p><strong>Record:</strong> lang attribute present, labelled inputs on key forms, images missing alt text, and any failing contrast on primary actions.</p>
<h3>46. Funnel coherence</h3>
<p>Trace one journey end to end: a blog post, to the feature page it relates to, to pricing, to trial. At each step, ask whether there is an obvious next action and whether the messaging carries over. Most SaaS funnels break at the first joint, where blog content offers no route into the product at all.</p>
<p><strong>Record:</strong> the traced path, and the specific step where the journey breaks.</p>
<hr />
<h2>Section 9: How do you check AI search visibility?</h2>
<p>SaaS is the category most exposed to answer engines, because "what is the best tool for X" is exactly the question buyers now type into ChatGPT before they open Google. Six manual checks.</p>
<h3>47. Recommendation presence in answer engines</h3>
<p>Ask ChatGPT, Perplexity, and Gemini the questions a buyer would: "best {category} software", "best {category} tool for {use case}", "{category} tools for startups". Note whether your product appears and where in the list. Then ask "{your product} vs {top competitor}" and check whether the engine has enough accurate information to compare fairly. Record which sources each answer cites, because that list is where the recommendation is actually being decided.</p>
<p><strong>Record:</strong> per engine and query, whether the product appears, its position, and the cited sources.</p>
<h3>48. Google AI Overview presence</h3>
<p>Search your category, comparison, and "best X for Y" queries in an incognito window. Note whether an AI Overview appears and expand the citation list. Comparison and alternatives queries trigger overviews often and sit at the highest intent, so weight those. The queries where an overview appears and cites only competitors are your priority list.</p>
<p><strong>Record:</strong> per query, whether an overview appears, the cited domains, and whether yours is among them.</p>
<h3>49. Review platform citation footprint</h3>
<p>This extends check 36 into the AI dimension, because the engines lean heavily on these sources. Compare your G2 and Capterra review volume, average rating, and date of the most recent review against your two main competitors. Then search Reddit for your category and your product name, and read the sentiment; Reddit is cited disproportionately often by answer engines.</p>
<p><strong>Record:</strong> review volume, rating, and recency for you and each competitor, plus Reddit mention count and sentiment.</p>
<h3>50. Answer-ready product content</h3>
<p>Check whether pricing exists as plain text rather than an image or a "contact us" wall, whether a comparison or alternatives page exists for engines to quote, and whether feature pages answer their core question in the first paragraph. Engines cannot compare what they cannot read, and cross-reference this with check 5: content that only exists after JavaScript execution is content some engines never see.</p>
<p><strong>Record:</strong> whether pricing is plain text, whether comparison content exists, and per feature page, how far down the direct answer sits.</p>
<h3>51. Product entity and structured data</h3>
<p>Run the homepage and key pages through the Rich Results Test and the Schema Markup Validator. Look for <code>SoftwareApplication</code> or <code>Product</code>, and <code>Organization</code> with a populated <code>sameAs</code> array linking to your G2, Capterra, LinkedIn, and Crunchbase profiles. The <code>sameAs</code> array is the thing most often left empty, and it is what ties your site to your off-site review footprint in a way machines can follow.</p>
<p><strong>Record:</strong> markup types found, missing fields, and the full <code>sameAs</code> list if present.</p>
<h3>52. AI crawler access and documentation indexability</h3>
<p>Open <code>yourdomain.com/robots.txt</code> and search for <code>GPTBot</code>, <code>OAI-SearchBot</code>, <code>ClaudeBot</code>, <code>PerplexityBot</code>, <code>Google-Extended</code>, <code>CCBot</code>, and <code>Bytespider</code>, recording whether each is allowed, blocked, or unmentioned. Then do the same for the docs or help subdomain, and check whether documentation is indexable at all. Engines cite docs constantly when answering "how do I do X in {product}", and gated or <code>noindex</code> docs forfeit all of it. Finally, request <code>yourdomain.com/llms.txt</code> and note the response.</p>
<p><strong>Record:</strong> the directive for each user-agent on each host, whether any block was intended, docs indexability, and the llms.txt status code.</p>
<hr />
<h2>FAQ</h2>
<h3>How long does a SaaS SEO audit take?</h3>
<p>Five to eight hours for a first full pass if you know the tools, spread over a couple of days. The rendering check and the feature page inventory take the longest. The AI search section takes under an hour and is usually where the surprises are, because most teams have never asked ChatGPT what it says about their product.</p>
<h3>What is different about auditing a SaaS site?</h3>
<p>Four things: client-side rendering can hide content from crawlers entirely, the app subdomain has to be excluded from the index without catching the marketing site, pricing and feature page structure decides most of the commercial keyword surface, and review platforms carry more weight than backlinks for both rankings and AI recommendations.</p>
<h3>Do I need paid SEO tools for this?</h3>
<p>No. Every check above runs on Search Console, PageSpeed Insights, Chrome DevTools, the free Screaming Frog tier, GA4, and free validators. Paid tools save real time on keyword gap analysis and backlink data once you are past a few hundred URLs, but they do not surface a category of problem the free set misses.</p>
<h3>How is this different from a general website audit?</h3>
<p>A <a href="/website-seo-audit-checklist/">website SEO audit</a> covers local SEO, generic conversion checks, and a standard keyword review. This one drops local entirely and replaces it with funnel-stage keyword mapping, trial and pricing page checks, integration and programmatic opportunity, and review platform footprint. The technical layer also adds rendering and app subdomain checks that a brochure site never needs.</p>
<h3>When should a SaaS company run its first audit?</h3>
<p>Once there is a marketing site with more than a handful of pages and Search Console has three months of data. Before that there is nothing to measure. If you are earlier than that, the question is <a href="/when-to-start-seo-saas-startup/">when to start SEO at all</a>, which is a different decision.</p>
<hr />
<h2>Closing</h2>
<p>Most SaaS SEO problems are structural rather than cosmetic: one features page instead of twelve, pricing behind a contact form, docs set to noindex, a trial flow that asks for a credit card. Those are decisions, and decisions are cheaper to change than rankings are to earn. If you would rather have the whole picture gathered and prioritized for you, a <a href="https://illucrum.com/audits/saas-seo-audit/">SaaS SEO audit</a> covers all 52 points, and the implementation can be handled from there.</p>
]]></content:encoded></item><item><title><![CDATA[Why Your Store Needs SEO Before Spending on Ads]]></title><description><![CDATA[Most online stores start spending on ads before their SEO is in order. That's the expensive way round.
The logic seems reasonable: buy traffic, get sales. But if your product pages are slow, your desc]]></description><link>https://blog.illucrum.com/why-your-store-needs-seo-before-spending-on-ads</link><guid isPermaLink="true">https://blog.illucrum.com/why-your-store-needs-seo-before-spending-on-ads</guid><category><![CDATA[SEO]]></category><category><![CDATA[ecommerce seo]]></category><category><![CDATA[SEO vs Paid Ads]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Mon, 20 Apr 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/ec4090af-3023-4512-9125-7e30a6ff2bdc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most online stores start spending on ads before their SEO is in order. That's the expensive way round.</p>
<p>The logic seems reasonable: buy traffic, get sales. But if your product pages are slow, your descriptions are thin, and your site has no structured data, paid visitors bounce at roughly the same rate as organic ones. You are paying for a bad result, not avoiding it.</p>
<p><strong>In short:</strong> Organic search drives around 43% of e-commerce traffic, making it the single largest channel. Running ads on a site that isn't ready to convert means paying per click to confirm the problem. The better sequence: run an seo audit, fix the foundation, then amplify with ad spend.</p>
<hr />
<h2>Where Does E-Commerce Traffic Actually Come From?</h2>
<p>Organic search is the dominant traffic source for online stores, accounting for roughly 43% of all e-commerce traffic. Social media, direct visits, email, and paid search each contribute, but none individually comes close.</p>
<p>This matters for budget allocation. If nearly half your potential visitors arrive through search and your site ranks poorly for the terms your customers actually use, that is not a paid advertising problem. It is an SEO problem. Ads can fill the gap temporarily; they cannot solve it structurally.</p>
<p>Most store owners treat organic traffic as a bonus. In practice, it is the baseline that everything else builds on.</p>
<hr />
<h2>What Happens When You Run Ads on a Broken Site</h2>
<p>Paid traffic is not a different kind of visitor. Someone who clicks an ad lands on the same product page, faces the same three-second load time on mobile, and sees the same thin 40-word description as anyone who arrived from search.</p>
<p>If those pages do not convert organic visitors, they will not convert paid ones either. The cost-per-acquisition stays high and the conversion rate stays low, not because the ad targeting is wrong, but because the site itself is not ready.</p>
<p>The issues that hurt organic rankings are the same ones that hurt conversion: poor content quality, missing schema markup, slow Core Web Vitals, no mobile optimisation. These are the same problems covered in the <a href="/blog/ecommerce-seo-checklist/">e-commerce SEO checklist</a>. Fixing them improves every channel simultaneously, including paid.</p>
<hr />
<h2>The ROI Gap: SEO vs Paid Over 12 Months</h2>
<p>The honest comparison here is not "SEO is free and ads cost money." SEO takes time and investment to do properly. But the compounding effect is real and the maths eventually favours it.</p>
<p>Ad spend produces results in direct proportion to budget. When the budget stops, the traffic stops. SEO rankings accumulate over time; a category page that ranks well in month nine continues generating traffic in month eighteen without an additional cost per click.</p>
<p>E-commerce SEO delivers around <a href="https://firstpagesage.com/reports/seo-roi-statistics-fc/">317% ROI</a> with a break-even point at roughly nine months, based on available industry benchmarks. Over the same period, paid search CPCs rose approximately 13% year-over-year in 2025. The cost of buying traffic is rising; the cost of ranking well is not.</p>
<p>Neither channel is the right answer in isolation. The argument is about sequence, not which one to choose permanently.</p>
<hr />
<h2>What an SEO Audit Finds That an Ad Dashboard Doesn't</h2>
<p>An ad dashboard tells you what is happening: click-through rate, cost per acquisition, ROAS, conversion rate. It does not tell you why.</p>
<p>An SEO audit examines the underlying site. Crawlability problems that prevent pages from being indexed. Content gaps where competitors rank and you do not. Technical debt slowing down page loads. Keyword coverage mismatches between what you target and what people search for. Backlink patterns that hold the domain back.</p>
<p>Fix the underlying site and every channel benefits. This is what most people actually mean when they talk about an <a href="https://blog.illucrum.com/ecommerce-seo">e-commerce SEO audit</a> and why we frame ours across 46 points covering technical health, content, keywords, backlinks, and competitor positioning, not just rankings.</p>
<p>An ad dashboard cannot surface any of this. It measures the outcome; the audit identifies the cause.</p>
<hr />
<h2>The Right Order: Audit, Fix, Then Amplify</h2>
<p>The sequence that produces the best return on total marketing spend is not complicated.</p>
<p>First, audit the site. Identify what is broken, what is missing, and where the gaps are relative to the competitors who are outranking you. This is the diagnostic phase; without it, fixes are guesses.</p>
<p>Second, fix the issues. Product page content, category page copy, page speed, schema markup, internal linking structure. None of these are instant, but all of them are finite. There is a bottom to the list.</p>
<p>Third, run ads. At this point, paid traffic lands on pages that are built to convert. Cost per acquisition drops. Organic rankings improve in parallel. Both channels perform better because the foundation is solid.</p>
<p>The reverse order, ads first and site optimisation later, means paying to send traffic to a store that is not ready for it.</p>
<hr />
<h2>When Ads Do Make Sense (Even Before SEO Is Perfect)</h2>
<p>This is not a case against advertising. There are situations where paid campaigns make sense before SEO work is complete.</p>
<p>New product launches are the clearest example. A product with no ranking history cannot rely on organic search. Ads bridge that gap while organic authority builds. Seasonal or time-limited promotions are another case; organic search cannot respond fast enough to a two-week sale, and paid can. Testing keyword intent before committing budget to a content strategy is also a legitimate use of paid campaigns.</p>
<p>The distinction is purpose. Ads used for testing, timing-sensitive promotions, or bridging a new launch are a deliberate tool. Ads used as a substitute for a site that doesn't perform are an ongoing cost attached to a fixable problem.</p>
<hr />
<h2>FAQ</h2>
<h3>Should I stop running ads while fixing my SEO?</h3>
<p>No. Pausing profitable ad campaigns while working on SEO is rarely necessary. The two can run in parallel. The goal is to make the site better so that both channels produce better results; that process does not require switching paid off. If campaigns are unprofitable before SEO is addressed, that is worth examining separately.</p>
<h3>How long does e-commerce SEO take to show results?</h3>
<p>For most e-commerce sites, meaningful movement in organic rankings begins between three and six months. Stable rankings with compounding traffic growth typically require nine to twelve months. This assumes technical issues are identified and resolved early; unaddressed problems extend that timeline considerably.</p>
<h3>What is the difference between an SEO audit and a marketing audit?</h3>
<p>A marketing audit reviews channel performance: spend, efficiency, and campaign results. An SEO audit examines the site itself; crawlability, indexation, content quality, keyword coverage, technical performance, and backlink profile. For e-commerce businesses, the SEO audit belongs first because site-level problems affect every channel including paid.</p>
<h3>Is organic traffic really free?</h3>
<p>Not exactly. Organic traffic has no cost per click, but generating it requires investment in content, technical work, and time. The difference from paid is that the investment is largely upfront, and the traffic it produces does not stop when the spend stops. Over a 12-to-24 month horizon, the unit economics tend to look significantly different.</p>
<hr />
<p>If you are currently spending on ads and have not looked closely at how the site is performing on search, an <a href="https://blog.illucrum.com/ecommerce-seo">e-commerce SEO audit</a> is a useful starting point. The audit takes a few days; the issues it identifies, fixed once, continue paying off long after the work is done. If you want a sense of what we typically find in stores at different stages, the <a href="https://blog.illucrum.com/ecommerce-seo-checklist">e-commerce SEO checklist</a> is a useful read first.</p>
]]></content:encoded></item><item><title><![CDATA[E-Commerce SEO Checklist (2026)]]></title><description><![CDATA[Most ecommerce SEO problems are structural. A store rarely loses organic traffic because of one bad title tag. It loses traffic because the same product sits at four different URLs, category pages con]]></description><link>https://blog.illucrum.com/ecommerce-seo-checklist</link><guid isPermaLink="true">https://blog.illucrum.com/ecommerce-seo-checklist</guid><category><![CDATA[ecommerce seo checklist]]></category><category><![CDATA[ecommerce seo mistakes]]></category><category><![CDATA[ecommerce seo]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Mon, 13 Apr 2026 08:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/eb2eec16-9e7a-4958-a783-8f78ad578fde.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p>Most ecommerce SEO problems are structural. A store rarely loses organic traffic because of one bad title tag. It loses traffic because the same product sits at four different URLs, category pages contain nothing but a product grid, and filtered views have quietly generated eleven thousand indexable pages. This ecommerce SEO audit checklist covers the 52 checks that surface those problems. It is deliberately limited to data gathering: what to look at, which tool to use, and what to write down. Deciding what the numbers mean, and what to fix first, is a separate job that gets much easier once the data is in front of you.</p>
<p><strong>In short:</strong> An ecommerce SEO audit covers eight areas: technical health, on-page elements, product and catalog structure, keyword coverage, competitors, backlinks, conversion UX, and AI search visibility. Running all 52 checks yourself takes roughly four to eight hours for a mid-sized store, using Google Search Console, PageSpeed Insights and a crawler.</p>
<hr />
<h2>What do you need before you start?</h2>
<p>Five tools cover almost everything. Only one of them costs money, and there is a free tier that will get you through a small store.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Used for</th>
<th>Cost</th>
</tr>
</thead>
<tbody><tr>
<td>Google Search Console</td>
<td>Query data, index coverage, crawl stats</td>
<td>Free (needs site ownership)</td>
</tr>
<tr>
<td>PageSpeed Insights</td>
<td>Speed and Core Web Vitals</td>
<td>Free</td>
</tr>
<tr>
<td>Screaming Frog SEO Spider</td>
<td>Site crawl, titles, headings, redirects, internal links</td>
<td>Free to 500 URLs, then paid</td>
</tr>
<tr>
<td>Rich Results Test / Schema Markup Validator</td>
<td>Product and breadcrumb schema</td>
<td>Free</td>
</tr>
<tr>
<td>Browser view-source and DevTools</td>
<td>Canonicals, rendering, meta directives</td>
<td>Free</td>
</tr>
</tbody></table>
<p>Two decisions to make before you begin. First, pick your sample: the homepage, your three biggest category pages, five to ten representative product pages (including one with variants and one out of stock), and one blog or guide page if you have them. Auditing every product page on a 4,000-SKU store is not useful and not necessary. Second, set your Search Console date range to the last three months and keep it consistent across every check, otherwise the numbers will not line up later.</p>
<p>If you have already run a general technical review, several checks below will look familiar. The overlap is intentional; the <a href="/blog/technical-seo-audit-checklist/">technical SEO audit checklist</a> goes deeper on crawling, rendering and security, while this one covers the catalog-specific layer that a generic audit misses.</p>
<hr />
<h2>Technical SEO checks (1 to 12)</h2>
<p>Ecommerce platforms generate URLs faster than anyone can manage them. This section is about finding out how many exist and which ones search engines are actually spending time on.</p>
<p><strong>1. Page speed.</strong> Run PageSpeed Insights on the homepage, your top category page and a top product page, on both mobile and desktop. Record all six performance scores. Product pages are usually the slowest because of image weight and review widgets.</p>
<p><strong>2. Core Web Vitals.</strong> From the same PageSpeed runs, record LCP, INP and CLS for each page. Note whether the results come from field data (real users) or lab data only, since a store with low traffic will often have no field data at all.</p>
<p><strong>3. HTTPS and SSL.</strong> Load the <code>http://</code> version of the homepage and record whether it returns a 301 to <code>https://</code>. Check the certificate expiry date and issuer. Run SSL Labs if you want the full picture.</p>
<p><strong>4. Mobile rendering.</strong> Open a product page on an actual phone, not just DevTools device mode. Record whether the image gallery swipes, whether size and color selectors are tappable, whether the add-to-cart button is reachable, and whether category filters work on touch.</p>
<p><strong>5. XML sitemap and robots.txt.</strong> Fetch <code>/sitemap.xml</code> and <code>/robots.txt</code> directly. Record the total URL count, whether the sitemap is split by type (products, collections, pages, blog), and whether any product or collection path appears in a <code>Disallow</code> rule.</p>
<p><strong>6. Canonical tags.</strong> Find a product that belongs to more than one collection and load it via both paths, for example <code>/products/item</code> and <code>/collections/collection/products/item</code>. Record the canonical URL each version returns. This single check catches the most common duplication problem in ecommerce.</p>
<p><strong>7. URL structure.</strong> Export the full URL list from your crawler. Record the maximum click depth, how many URLs contain query parameters, and whether any category URLs use numeric IDs instead of readable slugs.</p>
<p><strong>8. Product schema.</strong> Run three or four product pages through the Rich Results Test. Record which fields are present: <code>name</code>, <code>image</code>, <code>sku</code>, <code>brand</code>, <code>offers</code> with <code>price</code>, <code>priceCurrency</code> and <code>availability</code>, and <code>aggregateRating</code>. Note errors separately from warnings.</p>
<p><strong>9. Pagination.</strong> Open a category page with more products than fit on one screen. View the raw page source (not the rendered DOM) and record whether links to page two and beyond exist as standard <code>&lt;a href&gt;</code> elements. If products load via infinite scroll or a JavaScript "Load More" button with no fallback links, write that down.</p>
<p><strong>10. Tag and filter pages.</strong> Click a filter on a category page and record whether the URL changes. If it does, run a <code>site:</code> search in Google for that URL pattern and record how many are indexed. Check one of those pages for a <code>noindex</code> directive or a canonical pointing back to the parent category.</p>
<p><strong>11. Redirect chains and broken links.</strong> Crawl the site and export the response codes report. Record the number of 3xx responses, the longest redirect chain in hops, and the count of internal 4xx links along with which pages they sit on.</p>
<p><strong>12. Crawl budget and index bloat.</strong> In Search Console, open Indexing then Pages. Record the indexed count, the not-indexed count, and the breakdown by reason, particularly "Crawled - currently not indexed" and "Discovered - currently not indexed". Then compare the indexed count against your actual product plus category count.</p>
<hr />
<h2>On-page checks for product and category pages (13 to 20)</h2>
<p>These are standard on-page checks, but the volume changes how you run them. On a store with 2,000 products you are looking at a crawl export, not individual pages.</p>
<p><strong>13. Title tags.</strong> From the crawl export, record how many titles are missing, duplicated, over 60 characters, or under 30. Sort duplicates by count to see whether the pattern is template-driven.</p>
<p><strong>14. Meta descriptions.</strong> Same export. Record missing and duplicate counts, and check whether product descriptions are hand-written or auto-pulled from the first line of body copy.</p>
<p><strong>15. Heading structure.</strong> Record pages with zero H1s and pages with more than one. On product pages, check whether the H1 matches the product name and whether H2s break the description into sections.</p>
<p><strong>16. Image optimization and alt text.</strong> Export the images report. Record the number of images missing alt text, the number over 100KB, and which formats are in use. Note whether product photos carry descriptive alt text or filenames like <code>IMG_3421</code>.</p>
<p><strong>17. Internal linking.</strong> Export the inlinks report. Record the average number of internal links pointing to product pages, identify any orphan pages, and note whether the homepage links directly to your main categories.</p>
<p><strong>18. Category page content.</strong> For your top five categories, record the word count of text outside the product grid. Many stores score zero here, which is worth knowing precisely.</p>
<p><strong>19. Content depth versus competitors.</strong> Search your three main category keywords. For each of the top three ranking pages, record the word count and what content types appear: buying guides, FAQs, comparison tables, video.</p>
<p><strong>20. Open Graph tags.</strong> View source on a product page and record whether <code>og:title</code>, <code>og:description</code>, <code>og:image</code>, <code>og:type</code> and <code>og:url</code> are present, and whether <code>og:image</code> resolves to the primary product photo.</p>
<hr />
<h2>Product and catalog checks (21 to 28)</h2>
<p>This is the section a generic SEO audit does not have, and it is usually where the largest problems sit.</p>
<p><strong>21. Product page SEO quality.</strong> Take ten sample products and record five things per page in a single table: title tag, meta description, H1, canonical URL, and whether product schema is present. Reviewing them as a unit makes template-level failures obvious.</p>
<p><strong>22. Product description depth.</strong> For those same ten products, record the description word count. Then take one distinctive sentence from each, search it in Google inside quotation marks, and record how many other sites return the identical text. That tells you whether the copy is manufacturer-supplied.</p>
<p><strong>23. Category architecture.</strong> Map the hierarchy from the navigation menu and breadcrumb trails. Record how many levels deep it goes, how many categories are reachable from the main navigation, and whether subcategories exist as real pages or only as filters.</p>
<p><strong>24. Variant handling.</strong> On a product with multiple sizes or colors, click through each variant and record whether the URL changes, whether the canonical changes with it, and whether variant images have their own alt text.</p>
<p><strong>25. Out-of-stock and discontinued products.</strong> Find an out-of-stock product and record its HTTP status code and whether the page offers a back-in-stock option. Then find a product that has been discontinued and record whether the URL 404s, redirects, or still resolves.</p>
<p><strong>26. Faceted navigation.</strong> Count the filter dimensions on your largest category page and the number of options within each. Apply two filters at once and record whether the resulting URL is crawlable and indexable. Check <code>robots.txt</code> and meta robots for any rules covering those parameters.</p>
<p><strong>27. Product image SEO.</strong> Beyond alt text, record image filenames, how many angles each flagship product has, whether an image sitemap exists, and whether the schema <code>image</code> field points to the primary photo.</p>
<p><strong>28. Reviews on product pages.</strong> Disable JavaScript or compare raw source against the rendered page, and record whether review text appears in the HTML or only loads from a third-party widget. Record the review count and average rating for your top products, and whether <code>AggregateRating</code> schema is present.</p>
<p>If pulling all of this on a large catalog is more work than you want to take on, our <a href="/ecommerce-seo-audit/">ecommerce SEO audit</a> runs the same 52 checks and returns the findings written up.</p>
<hr />
<h2>Keyword, competitor and backlink checks (29 to 41)</h2>
<p>Everything here is comparative. The point is not what your store ranks for in isolation, but where the gap sits between you and the stores taking your traffic.</p>
<p><strong>29. Current ranking queries.</strong> In Search Console, open Performance then Search results. Sort by impressions and record the top 20 queries with position, CTR and clicks. Tag each one as branded, product, category, or informational.</p>
<p><strong>30. Category keyword coverage.</strong> List your five to ten core categories. Search each one the way a buyer would, in incognito, and record whether your store appears anywhere in the top 20 and which page ranks.</p>
<p><strong>31. Long-tail and modifier keywords.</strong> For each core category, record the Google autocomplete suggestions and the "People Also Ask" questions. Note which modifier types appear: brand, material, color, price, use case, audience. Then record whether you have a page targeting each pattern.</p>
<p><strong>32. Quick-win keywords.</strong> In Search Console, filter Performance to positions 4 through 20 and sort by impressions. Record the queries with meaningful impressions and the page currently ranking for each.</p>
<p><strong>33. Keyword gap.</strong> Using your competitor list from check 35, record product and category keywords where competitors have visibility and you have none.</p>
<p><strong>34. Branded versus non-branded split.</strong> In Search Console, filter queries containing your brand name and record the click total. Compare against total clicks and record the ratio.</p>
<p><strong>35. Top three organic competitors.</strong> Search your core category keywords in incognito and record which domains appear repeatedly in the top five. Include marketplaces such as Amazon or Etsy if they show up, since they compete for the same clicks whether or not you consider them rivals.</p>
<p><strong>36. Domain strength comparison.</strong> Run your domain and each competitor through the same tool, whichever you use, and record the authority score, referring domain count and indexed page count side by side.</p>
<p><strong>37. SERP features and shopping carousels.</strong> For your top ten commercial keywords, record which features appear: shopping carousel, product knowledge panel, image pack, People Also Ask, featured snippet. Record whether your products appear in any of them and which competitors do.</p>
<p><strong>38. Content gap.</strong> Record the content types competitors publish that you do not: buying guides, "best of" roundups, comparison articles, how-to content, video.</p>
<p><strong>39. Backlinks and referring domains.</strong> Record total backlinks and unique referring domains for your store and each competitor from check 35.</p>
<p><strong>40. Toxic backlinks.</strong> Scan your referring domain list and record any obvious patterns: irrelevant foreign-language sites, link networks, repeated exact-match anchor text.</p>
<p><strong>41. Competitor link gap.</strong> Record domains that link to at least two competitors but not to you, sorted by relevance.</p>
<hr />
<h2>Cart, checkout and conversion checks (42 to 46)</h2>
<p>Organic visitors arrive cold. They have no ad context, no prior brand exposure, and no reason to trust the store yet.</p>
<p><strong>42. Navigation.</strong> Record the number of top-level navigation items, whether a search bar is visible without scrolling, whether breadcrumbs appear on product pages, and whether the menu structure matches the category hierarchy from check 23.</p>
<p><strong>43. Cart and checkout indexation.</strong> Load <code>/cart</code> and <code>/checkout</code> and record whether each carries a <code>noindex</code> directive. Run a <code>site:</code> search for cart and checkout URLs and record how many are indexed. Note whether checkout hands off to a different domain.</p>
<p><strong>44. Trust signals.</strong> On a product page, record which of these are visible: payment method icons, return policy link, shipping cost or threshold, delivery timeframe, customer reviews, third-party trust badge, and a contact method that is not a form.</p>
<p><strong>45. Layout and readability.</strong> On mobile, record whether price, availability and the add-to-cart button are visible without scrolling, and how far down the page the product description begins.</p>
<p><strong>46. Conversion funnel trace.</strong> Walk the full path yourself: Google result, category page, product page, add to cart, checkout. Record the number of clicks, the number of form fields at checkout, whether guest checkout exists, and any point where the next action is unclear.</p>
<hr />
<h2>AI search and answer engine checks (47 to 52)</h2>
<p>Shopping queries increasingly resolve inside an AI answer rather than a results page. These checks establish whether your products appear there at all.</p>
<p><strong>47. AI Overviews.</strong> In incognito, search four to six high-intent commercial queries covering your top categories, "best [product] for [use case]" phrasing, and flagship product names. Record whether an AI Overview appears, which sources it cites, and whether your domain is among them.</p>
<p><strong>48. Assistant recommendations.</strong> Ask ChatGPT in search mode, Perplexity and Gemini the same category and use-case shopping questions. Record whether your brand or products are recommended, which competitors are, and which sources each engine cites. The cited sources matter more than the recommendation itself; they show you what needs to change.</p>
<p><strong>49. Product structured data for AI.</strong> This extends check 8. Record whether <code>gtin</code> or <code>sku</code> identifiers are present, whether <code>Organization</code> markup includes <code>sameAs</code> links, and whether <code>BreadcrumbList</code> exists on category pages. Flag any product where price, stock or rating is visible on the page but absent from the markup.</p>
<p><strong>50. Review signal strength.</strong> For your top five products, record review count, date of the most recent review, and average rating. Record the same for the equivalent competitor products. Note whether ratings appear in Google Shopping results and whether you have a third-party review profile.</p>
<p><strong>51. Buying guide and comparison content.</strong> Record whether the store publishes "best [product] for [use case]" guides, "[A] vs [B]" comparisons, or gift guides. For any that exist, record whether the recommendation appears in the first hundred words and whether a comparison table is present.</p>
<p><strong>52. AI crawler access and feed health.</strong> Check <code>robots.txt</code> for rules covering <code>GPTBot</code>, <code>OAI-SearchBot</code>, <code>ClaudeBot</code>, <code>PerplexityBot</code>, <code>Google-Extended</code> and <code>CCBot</code>, and record whether each is allowed, blocked, or unaddressed. Check whether <code>/llms.txt</code> exists. In Google Merchant Center, record the product feed status and the number of disapproved items.</p>
<hr />
<h2>Frequently asked questions</h2>
<h3>How long does an ecommerce SEO audit take?</h3>
<p>Four to eight hours for a store with a few hundred products, assuming Search Console access and a working crawl. Larger catalogs take longer, mainly because export files get unwieldy and faceted navigation takes real time to map. The crawl itself can run unattended, so plan around it rather than waiting on it.</p>
<h3>Which checks matter most for Shopify stores?</h3>
<p>Checks 6, 10 and 24. Shopify serves the same product at both <code>/products/</code> and <code>/collections/.../products/</code> paths, generates an indexable URL for every tag within a collection, and handles variants in ways that vary by theme. These three account for most Shopify duplication problems. Check 23 also matters, since Shopify has no true parent-child collection structure.</p>
<h3>Do I need paid tools to run this?</h3>
<p>No, though a crawler makes checks 7, 11, 13 to 17 considerably faster. Screaming Frog is free up to 500 URLs, which covers a small store completely. Everything else on this list runs on Search Console, PageSpeed Insights, the Rich Results Test, and your browser.</p>
<h3>How often should I run this?</h3>
<p>Once fully, then quarterly for the technical and index checks, which are the ones that drift as the catalog changes. Product and content checks are better handled continuously as you add SKUs. Re-run the full checklist after any platform migration, theme change or major catalog restructure.</p>
<hr />
<p>Gathering the data is the part most stores skip, and it is the part that makes every later decision straightforward. Work through the 52 checks, record the results in one place, and the priorities tend to declare themselves. If you would rather not spend the weekend on export files, an <a href="https://illucrum.com/audits/ecommerce-seo-audit">ecommerce SEO audit</a> covers the same ground and comes back with the findings and a fix order.</p>
]]></content:encoded></item><item><title><![CDATA[Shopify SEO: 7 Issues the Platform Creates]]></title><description><![CDATA[Shopify makes launching an online store fast. It handles hosting, SSL, sitemaps, and basic mobile responsiveness out of the box. What it does not handle well is the structural SEO work that determines]]></description><link>https://blog.illucrum.com/shopify-seo</link><guid isPermaLink="true">https://blog.illucrum.com/shopify-seo</guid><category><![CDATA[shopify]]></category><category><![CDATA[SEO]]></category><category><![CDATA[shopify seo]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Mon, 06 Apr 2026 07:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6938690abe359741ad261496/aea8d1d7-a1bc-4071-8f62-dfcfe4353d2a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Shopify makes launching an online store fast. It handles hosting, SSL, sitemaps, and basic mobile responsiveness out of the box. What it does not handle well is the structural SEO work that determines whether your store actually appears in search results. The platform's rigid URL system, automatic duplicate content generation, and limited control over indexing create problems that most store owners never notice until their rankings stall.</p>
<p>This is not a general SEO guide. It is specifically about the issues Shopify introduces and what you can do about them. If you are running a Shopify store and organic traffic is not where it should be, at least one of these is probably why.</p>
<p><strong>In short:</strong> Shopify is a strong e-commerce platform, but its default settings create duplicate content, bloated indexes, and thin pages that hurt search rankings. Fixing these platform-specific issues is the fastest path to better organic performance for most Shopify stores.</p>
<h2>1. Duplicate Product URLs</h2>
<p>This is Shopify's most persistent SEO problem, and it is baked into the platform's architecture. When a product belongs to more than one collection, Shopify creates a separate URL for each collection path.</p>
<p>A single pair of running shoes might be accessible at <code>/products/trail-runner-pro</code>, <code>/collections/mens-shoes/products/trail-runner-pro</code>, and <code>/collections/new-arrivals/products/trail-runner-pro</code>. All three URLs serve identical content.</p>
<p>Shopify adds canonical tags that point to the <code>/products/</code> version, which helps. But the internal links on your site, particularly from collection pages, often point to the collection-based URL rather than the canonical one. This sends mixed signals to search engines about which version matters and splits your link equity across multiple pages.</p>
<p>The fix has two parts. First, audit your internal links to ensure they point to the canonical <code>/products/</code> URL, not the collection path. This usually requires editing your theme's Liquid templates. Second, use Google Search Console to verify that the correct URLs are being indexed and that duplicate versions are not appearing in search results.</p>
<h2>2. Tag Pages and Index Bloat</h2>
<p>Shopify generates a new page every time you use tags to filter products within a collection. If you sell clothing and use tags like "cotton," "long-sleeve," "red," and "summer," each combination creates a unique, indexable URL.</p>
<p>These tag pages carry the same products as your main collection page, with no way to add unique titles, descriptions, or introductory content through Shopify's standard admin. From Google's perspective, they are thin, duplicate pages. A store with 20 collections and 10 tags per collection can accidentally generate 200 near-identical pages competing with your actual category pages.</p>
<p>The most reliable fix is adding a noindex directive to tag pages. This keeps them functional for shoppers (they can still filter products) while preventing search engines from treating them as separate pages. You can do this by adding conditional logic to your theme's <code>&lt;head&gt;</code> section that inserts a noindex meta tag when the URL contains a <code>/tagged/</code> path.</p>
<p>If specific tag pages genuinely target unique keywords (for example, a "vegan leather" tag page in a handbag store), you can selectively allow indexing for those pages while noindexing the rest. But this is the exception, not the rule.</p>
<h2>3. Thin Product and Collection Content</h2>
<p>Shopify's content editing tools are functional but basic. The product description field is a simple rich text editor, and collection pages default to displaying a product grid with minimal or no descriptive text. Many store owners leave these fields empty or paste in the manufacturer's default description.</p>
<p>Both choices hurt search rankings. Empty or near-identical descriptions mean Google has no unique content to index on these pages. When the same manufacturer description appears on your store and 30 competitors' stores, none of you will rank well for it.</p>
<p>For product pages, write original descriptions of at least 150 to 300 words per product. Lead with benefits and use cases rather than technical specifications. Include your primary keyword within the first 100 words, and add secondary terms naturally throughout.</p>
<p>For collection pages, add 200 to 300 words of unique descriptive copy above or below the product grid. This is the single most underrated optimisation for Shopify stores. Collection pages can rank for high-volume category keywords ("women's running shoes," "organic skincare") that individual product pages cannot.</p>
<h2>4. Rigid URL Structure</h2>
<p>Shopify enforces a fixed URL structure that you cannot change. Products always live under <code>/products/</code>, collections under <code>/collections/</code>, blog posts under <code>/blogs/[blog-name]/</code>, and pages under <code>/pages/</code>. There is no way to create a custom URL hierarchy like <code>/shoes/running/trail-runner-pro/</code>.</p>
<p>This is not a serious ranking disadvantage on its own. Google can rank pages regardless of their URL path. But it does mean your URLs provide less contextual information to search engines than a flexible platform like WooCommerce would allow.</p>
<p>Where this becomes a practical problem is in breadcrumb navigation. Shopify's default breadcrumbs are naturally shallow because there is no true parent-child category relationship in the URL structure. You can implement breadcrumb schema markup to help Google understand your site hierarchy even though the URLs don't reflect it, but this requires manual coding in your theme.</p>
<p>Focus your effort on what you can control: make URL slugs short and descriptive (edit the "URL and handle" field for every product and collection), and use internal linking to establish the relationships between pages that the URL structure cannot express.</p>
<h2>5. Page Speed and Theme Bloat</h2>
<p>Shopify's hosted infrastructure is fast by default. The problems come from what store owners add on top of it: heavy themes, too many apps, unoptimised images, and third-party scripts.</p>
<p>Every Shopify app you install adds JavaScript and CSS to your pages. A store with 15 apps can easily add two to three seconds of load time. Many of these apps continue loading their scripts on every page even when their functionality is only needed on one.</p>
<p>Themes are another factor. A theme that looks impressive in the Shopify Theme Store might have render-blocking JavaScript, unoptimised image delivery, and poor Core Web Vitals scores. According to industry data, a large majority of Shopify stores load slower than Google's recommended thresholds.</p>
<p>The fixes here are straightforward but require discipline. Audit your installed apps and remove anything you are not actively using. Compress all product images before uploading (tools like TinyPNG or Squoosh work well). Choose a lightweight theme, or have your current theme audited for performance issues. Use lazy loading for images below the fold.</p>
<h2>6. Missing or Generic Structured Data</h2>
<p>Shopify does not include rich schema markup by default. Some themes add basic Product schema, but many do not include critical fields like review ratings, availability, price currency, or brand information.</p>
<p>Without proper structured data, your products cannot appear in Google's rich results (the listings that show star ratings, prices, and stock status directly in search results). They also cannot appear in Google Shopping's free product listings. In 2026, with AI-generated search overviews pulling structured data to answer product queries, missing schema means your store is invisible in an increasing share of search results.</p>
<p>The implementation path depends on your technical comfort level. You can add Product schema directly to your theme's Liquid templates, use a Shopify app like Smart SEO or JSON-LD for SEO, or have a developer implement it. Whichever method you choose, validate the markup afterwards using Google's Rich Results Test. Broken schema can actually prevent your pages from displaying correctly, so validation is not optional.</p>
<p>At minimum, every product page should include: product name, description, brand, SKU or GTIN, price, currency, availability status, and aggregate review rating (if you have reviews). Collection pages benefit from FAQ schema if you add descriptive content that answers common questions about the product category.</p>
<h2>7. Limited Blog Functionality</h2>
<p>Shopify includes a built-in blog, but it is basic compared to WordPress or dedicated content platforms. You get a title, a rich text body, tags, and a featured image. There is no table of contents generation, no advanced layout options, no native support for FAQ schema, and limited control over URL structure.</p>
<p>This matters because content marketing is how online stores capture informational and long-tail keywords that product pages cannot target. "How to choose running shoes for flat feet" or "best materials for kitchen knives" are searches that a blog post can rank for and that a product page never will.</p>
<p>The blog limitation is a genuine constraint, but it is not a reason to skip content entirely. You can work around most of the formatting issues by editing HTML within blog posts, and FAQ schema can be added to your theme's blog template. Some stores opt for a separate blog on a subdomain (using WordPress or a platform like Hashnode) to get more flexibility, though this introduces additional complexity around domain authority and link equity.</p>
<p>What matters more than the platform is consistency. A Shopify blog with one well-written, keyword-targeted post per month will outperform no blog at all. Start with topics your customers actually search for: buying guides, size guides, material comparisons, care instructions. Each post should link to relevant product and collection pages, creating the internal linking network that both users and search engines rely on.</p>
<h2>Frequently Asked Questions</h2>
<h3>Is Shopify good for SEO?</h3>
<p>Shopify handles many SEO fundamentals well: SSL, mobile responsiveness, XML sitemaps, and canonical tags are all included by default. But the platform's rigid URL structure, duplicate content generation, and limited technical control create issues that require manual fixes. Shopify is a capable SEO platform, but it is not a hands-off one.</p>
<h3>Does changing my Shopify theme affect SEO?</h3>
<p>It can. A new theme may change your page load speed, heading structure, schema markup, and mobile layout. Before switching themes, benchmark your current Core Web Vitals scores and review the new theme's code quality. After switching, re-validate your structured data and check Google Search Console for any new crawl errors.</p>
<h3>How do I fix duplicate content on Shopify?</h3>
<p>Shopify's duplicate content comes primarily from two sources: products appearing in multiple collections (creating multiple URLs) and tag pages. For collection-based duplicates, ensure internal links point to the canonical <code>/products/</code> URL. For tag pages, add a noindex directive to your theme's <code>&lt;head&gt;</code> section for any URL containing <code>/tagged/</code>.</p>
<h3>Do I need a Shopify SEO app?</h3>
<p>An SEO app can help with bulk editing meta tags, generating structured data, and automating image alt text. If you have hundreds of products, the time savings are significant. Smart SEO and JSON-LD for SEO are well-regarded options. Avoid installing multiple SEO apps, as they often conflict with each other and add unnecessary load time.</p>
<h3>How often should I audit my Shopify store's SEO?</h3>
<p>A full audit once or twice per year is a reasonable starting point. Between audits, monitor Google Search Console monthly for crawl errors, indexing issues, and keyword performance changes. Any time you add a significant number of products, change themes, or install new apps, check your technical SEO metrics to catch regressions early.</p>
<h2>What to Do Next</h2>
<p>Shopify's SEO challenges are real, but they are also well-understood and fixable. Most stores underperform in search not because the platform is fundamentally limited, but because these platform-specific issues go unaddressed.</p>
<p>If your store's organic traffic is flat or declining, the issues above are the first place to look. An <a href="https://illucrum.com/audits/ecommerce-seo-audit">e-commerce SEO audit</a> built specifically for Shopify will identify exactly which of these problems exist on your store and prioritise fixes by impact. If you already know what needs fixing, the optimisation work can be handled for you.</p>
]]></content:encoded></item><item><title><![CDATA[A "perfect" data structure]]></title><description><![CDATA[Algorythms, data structures and maths. Those are the three legs of the tripod that holds programming. Today, let’s focus on data structures. You know how each one has it strengths and weakneses, each one has it’s own use cases. A “perfect” data struc...]]></description><link>https://blog.illucrum.com/a-perfect-data-structure</link><guid isPermaLink="true">https://blog.illucrum.com/a-perfect-data-structure</guid><category><![CDATA[Programming Blogs]]></category><category><![CDATA[data structures]]></category><category><![CDATA[list]]></category><category><![CDATA[Complexity]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Thu, 29 Jan 2026 08:00:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769624313917/06cab449-d293-4324-9f58-76b1d7aaef7f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Algorythms, data structures and maths. Those are the three legs of the tripod that holds programming. Today, let’s focus on data structures. You know how each one has it strengths and weakneses, each one has it’s own use cases. A “perfect” data structure should only have strengths and no weakneses, but it should also be useful in all situations. Which is of course ridiculous. There is just no way you can have a data structure that would be able to replace a regular list, just the same as it would be able to replace a tree. Although it’s worth mentioning that a binary tree can be implemented with an array. In this article, I’ll explore the posibilities of coming closer to the “perfect” data structure by trying to design one that would behave like a list while assuring a O(1) complexity for all relevant operations.</p>
<h2 id="heading-algorythmic-complexity">Algorythmic complexity</h2>
<p>Although this article is not about complexity, let’s briefly explain what it is about. The complexity of an algorythm is used to predict how an algorythm will perform depending on the input size. This is very important for data structures that can hold millions of entries. So for example, if we assume a simple node list of which we only have direct access to the first node, if we want to add a new item to it at the beggining, no matter how long the list is, it will always cost the same ammount of resources, which is very good. But if we want to add a new item at the end, we would need to iterate through the whole thing. In this case the time needed to add this new item would be roughly directly proportional to the length of the list.</p>
<p>In some other situations, things are not always that simple. Sometimes the resources needed don’t depend only on the size of the input. Which is very common for sorting algorythms, for example. In those situations, normally the worst case scenario is the most relevant. And this is where the big-o notation comes in, as a way to represent the complexity of an algorythm in it’s worst case scenario. From the previous example of the node list, adding an item at the beggining presents constant complexity, which is O(1). This basically means, it always needs the same amount of resources, no matter how long the list is. Adding an element at the end, presents linear complexity, which is O(n), where n represents the lenght of the list.</p>
<h2 id="heading-the-perfect-list">The “perfect” list</h2>
<h3 id="heading-goals">Goals</h3>
<p>First, let’s define the goals that the list I’m trying to describe should meet. The goal is to have a data structure on which we can perform these operations with O(1) complexity:</p>
<ul>
<li><p>Retrieving any element given it’s index</p>
</li>
<li><p>Adding a new element on any position</p>
</li>
<li><p>Removing any element</p>
</li>
</ul>
<p>As we can retrieve any element given it’s index, there should be of course no problem with iterating the list. So this goals should really cover it all.</p>
<h3 id="heading-restrictions">Restrictions</h3>
<p>This list will have one very important restriction. It will have a set maximum size. This is sadly necessary, I don’t see the possibility of avoiding this restriction.</p>
<h3 id="heading-structure">Structure</h3>
<p>It’s clear to me, that in a way, what I’m trying to achieve is to create something like an “indexed hash table”. This seems to be the most promising approach. To start with, let’s set the maximum size to 4 elements. This should give as a list big enough to see more clearly how it works, but also small enough to make it quite simple to simulate. The list will have the following components:</p>
<ul>
<li><p>The buckets: there should be as many buckets as many elements the list can hold at the same time. In our case it will have 4 bucket. Each will have it’s own identification binary number assigned to it, so we will have buckets 00, 01, 10 and 11. The buckets will really behave like wrappers of the elements stored in the list, and they themselves will be stored in a hash map, using their identifiers as keys. This will assure that we can access any element given it’s bucket number with constant complexity.</p>
</li>
<li><p>A size variable: there should be a variable to keep track of the current size of the list. Nothing special about it.</p>
</li>
<li><p>The state number: the buckets hold the elements, but it’s important to have a way of keeping track of how the buckets are odered. As our list can hold at most 4 buckets, and each has a 2 bits long key, an 8 bit long number will be used , which will contain the four buckets identifiers concatenated, in the order in which the buckets are ordered. Let’s consider the least significant two digits represent the first bucket, the two most significant digits represent the last bucket on the list.</p>
</li>
</ul>
<p>The size variable, is there mostly to make sure the inputs are valid. Most of the magic will happen with the state number, as by manipulating it the order of the buckets will be read and written.</p>
<p>So for example, let’s say we start with a list like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>State number</td><td>Size</td><td>Elements ordered from left to right</td></tr>
</thead>
<tbody>
<tr>
<td>00 01 10 11</td><td>3</td><td>1 - 2 - 4</td></tr>
</tbody>
</table>
</div><p>This would mean we would have a list with three elements, bucket 11 holding value “1“, bucket 10 holding value “2“ and bucket 01 holding the value “3“, while the bucket 00 remains empty. So now let’s say we want to add a “3“ between the “2” and the “4”. We would put the value “3” into the empty bucket 00, and place it between the buckets 01 and 10. This would give us:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>State number</td><td>Size</td><td>Elements ordered from left to right</td></tr>
</thead>
<tbody>
<tr>
<td>01 00 10 11</td><td>4</td><td>1 - 2 - 3 - 4</td></tr>
</tbody>
</table>
</div><p>Now, every bucket has a value attached to it. If we wanted to remove the first value (index 0), we would empty the bucket 11, and move it to the “end”. So our list should look like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>State number</td><td>Size</td><td>Elements ordered from left to right</td></tr>
</thead>
<tbody>
<tr>
<td>11 10 00 10</td><td>3</td><td>2 - 3 - 4</td></tr>
</tbody>
</table>
</div><h3 id="heading-retrieving-any-element-given-its-index">Retrieving any element given it’s index</h3>
<p>This is fairly simple. It’s sufficient to first check if the given index is allowed. Obviously you can never get the third element from a list with only two elements in it. For that we have the size variable. Once the given input is checked, we need to check which bucket is located at the indicated index. We can do that using the following formula:</p>
<p>$$b = {s \bmod 2^{2*(i+1)} \over 2^{2*i}}$$</p><p>Where <em>b</em> is the bucket number, we of course ignore any decimals; <em>s</em> is the state number and <em>i</em> is the index.</p>
<p>This way, no matter how long the the list is, we can retrieve any element by “just“ calculating the proper bucket. So it presents O(1) complexity.</p>
<h3 id="heading-adding-a-new-element-anywhere">Adding a new element anywhere</h3>
<p>First things first, we of course need to validate the input. After that we should get the last bucket, which will be always empty if the list is not full. This can be done using the previous formula and giving the index the value of 3. Once we have the bucket we can set it’s value. The we need then to modify the state number accordingly. To do so, we can use the following formula:</p>
<p>$$s\prime=s mod 2^{2i} + b * 2^{2i} + {{s/2^{2i}} * 2^{2(i+1)}}$$</p><p>Where <em>s’</em> is the new state number, we only care about the binary eight least significant digits; <em>s</em> is the old state number, <em>i</em> is the index and <em>b</em> is the bucket we are using.</p>
<p>And of course we need to update the index.</p>
<p>This time it’s not as simple as before, as we have to perform two calculations, not just one. But still the algorythm is independent from the lenght of the list, giving it the desired complexity.</p>
<h3 id="heading-removing-any-element">Removing any element</h3>
<p>By now it should be more or less clear how this will look like. First we need the make sure that the index we are given is valid. Then, we will retrieve the bucket for that index in the same fashion that we did before, so we can empty it. And then we can use the following formula to put the bucket at the “end”:</p>
<p>$$s\prime=(s-smod2^{2*(i+1)}/2^2)+(smod2^{2i})+b2^6$$</p><p>Where <em>s’</em> is the new state number, <em>s</em> is the old state number, <em>i</em> is the index and <em>b</em> is the bucket.</p>
<p>And last but not least, we of course need to update the index.</p>
<p>And also in this case, it’s enough to perform two calculations to remove any element with complexity O(1).</p>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p>This list idea, surely could be optimized. For example, as the number of states is finite, no calculations are really needed. It would be enough to map the whole thing, basically making a finit state machine. Nevertheless, this solution has a big drawback. And that is the maximum length.</p>
<p>Nowadays, we are using 64 bit processors. The biggest list could have at most 16 elements, each with a 4 bit id, which gives as a state number of 64 bits long. This would allow us to perform the calculations easily. Surely it’s possible to do maths with numbers longer than 64 bits on 64 bit processors, but something tells me that this wouldn’t really work fast enough. But maybe I’m mistaken.</p>
<p>On the other hand, designing finite state machines should always work quite well, but that would be very memory heavy. And of course it would also take a lot of time to design and then implement. But maybe it is worth a try?</p>
]]></content:encoded></item><item><title><![CDATA[Class loading and linking in Java]]></title><description><![CDATA[As Java is an object oriented language, the topic of what classes actually are and how are they loaded by the JVM, is one that really goes to the heart of things. In this article, we will explore in more detail not only what is visible to every Java ...]]></description><link>https://blog.illucrum.com/class-loading-and-linking-in-java</link><guid isPermaLink="true">https://blog.illucrum.com/class-loading-and-linking-in-java</guid><category><![CDATA[Java]]></category><category><![CDATA[classloader]]></category><category><![CDATA[jvm]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Tue, 16 Dec 2025 08:00:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765623238231/c274ff4a-ce0a-41f3-9e25-55692b356463.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As Java is an object oriented language, the topic of what classes actually are and how are they loaded by the JVM, is one that really goes to the heart of things. In this article, we will explore in more detail not only what is visible to every Java developer, but also what is hidden under the hood of the JVM.</p>
<h2 id="heading-class-loaders">Class loaders</h2>
<p>Let’s keep it relatively simple for a while, and let’s start with something more “tangible“ for a regular developer like tha class loaders. Class loaders, most often are Java classes extending <code>java.lang.ClassLoader</code>, which are responsible for loading other classes. To be more precise, they load the bytecode of a class, then they leave it to the JVM to do the linking, basically reading and analyzing the bytecode to create a new class.</p>
<h3 id="heading-hierarchy"><strong>Hierarchy</strong></h3>
<p>By default, a Java application has three main class loaders:</p>
<ol>
<li><p><strong>Bootstrap loader:</strong> The first class loader to run, it is used to get the absolute basic system loaded - essentially <code>java.base</code>. It is not a Java class, it’s written in native code and it doesn’t perform any checks on the classes it loads, so for security reasons it doesn’t have a representation in Java (as a class or class instance, for exmaple), and for this reason it’s refered as <code>null</code>.</p>
</li>
<li><p><strong>System loader:</strong> When the bootstrap loader is done loading the core of the system, the systen loader loads the platform modules that the application depends on. This class loader is a Java, as we said earlier, extending <code>java.lang.ClassLoader</code>. Not only it’s accessible through a static function (<code>ClassLoader.getSystemClassLoader()</code>), it can also be set when starting the application. So if you want to run your app with a custom system class loader, you just need to add to your command the <code>-Djava.system.class.loader=my.custom.ClassLoader</code> flag.</p>
</li>
<li><p><strong>Application loader:</strong> The last loader to run, is the most widely used. It’s basically the one that loads the application itself. It is also an instance of a Java class, just like the system class loader.</p>
</li>
</ol>
<h3 id="heading-delegation">Delegation</h3>
<p>Generally speaking, a class in Java can’t be loaded twice by the same class loader, but it can be loaded multiple times by different class loaders. This is one reason why there is a hierarchy of class loaders. And the second reason, is delegation, which purpose is precisely to avoid the same class to be loaded twice. A properly implemented class loader always delegates that task to it’s parent (the class immediately above in the hierarchy) before attempting to load it by itself. So, let’s say we want the application class loader to load the class A.</p>
<ol>
<li><p>The application loader delegates the task to the system class loader.</p>
</li>
<li><p>The system loader delegates the task to the bootstrap class loader.</p>
</li>
<li><p>The boostrap class loader has no parent, so it tries to load A and if it is able to do so, it returns it to the system loader.</p>
</li>
<li><p>When the system loader receives A from its parent, it just passes it through to the application loader. If not, it tries to load A by itself and return it to the application loader.</p>
</li>
<li><p>If the application loader receives class A from the system loader, there is nothing more to do. If it doesn’t, then the application loader is the last one to give it a try.</p>
</li>
</ol>
<p>Of course, you may add your own, totally custom class loaders. And those, although it would be a good thing if they followed delegation placing themselves beneath the app loader, in some cases they are implemented to break that rule on purpose.</p>
<h3 id="heading-initiating-and-defining-loaders">Initiating and defining loaders</h3>
<p>A class loader is said to be the defining loader of a class A, if A was actually loaded by that class loader. So if the app loader was the one that started the loading process, but due to delegation it was the bootstrap loader that actually found and loaded A, then the bootstrap loader is the defining loader of A.</p>
<p>A class loader is said to be the initiating loader a class A, if the class loader is either the one that started the process that loaded A or is also the defining loader of A. This means a class A can have two initiating class loadeds. In the previous example, the initiating class loaders would be both the app loader and the bootstrap loader.</p>
<p>This is quite important, we will talk about it later on.</p>
<h2 id="heading-jvm">JVM</h2>
<p>Now that we know what class loaders do, let’s focus on what the JVM does. This is where the fun really begins. This part is maybe a little bit more abstract as I will try to explain the concepts without getting into the details of specific implementations. The JVM is the responsible for making sure everything is secure and optimized so there is no errors and no unnecessary calls to the class loaders.</p>
<h3 id="heading-linking">Linking</h3>
<p>When a class loader finds the bytecode of the class to be loaded, the JVM takes over and starts creating it’s own representation of the class. This is refered to as linking and it is done in four steps:</p>
<ol>
<li><p><strong>Verification:</strong> First, the JVM needs to make sure that the bytecode loaded is a valid representation of a class and that it’s code is well behaved.</p>
</li>
<li><p><strong>Preparation:</strong> Once the bytecode is verified, the JVM starts allocating and getting the static variables of the class making them ready to initialize.</p>
</li>
<li><p><strong>Resolution:</strong> Now, before initializing the class, the JVM tries to resolve the supertype and implemented interfaces if any of the class being linked. If the JVM is not able to resolve them, it first tries to load and link them before continuing.</p>
</li>
<li><p><strong>Initialization:</strong> In this step, it’s the first time the bytecode of the class is actually being executed. In this step, all static fields are initialized as well as any static initialization blocks are run. When this is done, the class is ready to be instantiated.</p>
</li>
</ol>
<h3 id="heading-klasses">Klasses</h3>
<p>The representation of a class used by the JVM is the “klass” and it is not a Java class, they are stored in the metaspace. Each klass is unique, and all instaces of the class it represents, are created based on of that klass. Some of the information it contains is accessible from Java through the <code>java.lang.Class</code>, which instances are Java representations of different classes. This is what makes reflection possible, but that is a topic for a different article.</p>
<p>In the metaspace, klasses are not just stored in any way, they are organized. Each class loader has a dictionary assigned to it. Each klass is stored in the dictionary of it’s initiating loader. And it’s also important to point out, that each klass contains information about it’s defining loader.</p>
<h3 id="heading-loading-and-linking-process">Loading and linking process</h3>
<p>Let’s consider a class A, which has been defined by the app class loader. And let’s also consider a class B that is being referenced from A.</p>
<ol>
<li><p>When B is referenced while executing A, the JVM finds out from A’s klass which is it’s defining class loader, in our example it’s the app loader.</p>
</li>
<li><p>The JVM now check in the app loader’s dictionary if contains B. Which we could also express as, the JVM checks if the class loader already is an initiating loader for B. If it is, the JVM grabs the B klass and continues executing A.</p>
</li>
<li><p>But if the app loader is not an initiating loader of B, the JVM asks the app loader to load B.</p>
</li>
<li><p>Now all delegation steps explained before follow.</p>
</li>
<li><p>When B get’s loaded, it’s klass representation gets stored inside it’s initiating class loaders dictionaries for future reference.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Klasses are the representation of Java classes in the JVM. They are not only identified by their name, but also by their defining class loader. This is the reason why a class can be loaded multipple times by different class loader and get treated as completely different classes. Which is the reason why delegation and class loaders hierarchy is needed. Klasses are stored in the metaspace in a dictionary assigned to it’s initiating loaders, which helps the JVM to improve performance in not having to call the class loader each time some class gets referenced.</p>
]]></content:encoded></item><item><title><![CDATA[Java Hot Code Reloader]]></title><description><![CDATA[Without a doubt, Java is a wonderful language. It's fast, strongly typed, has C-like syntax, basically everything I like in a programming language. And also it has some other useful features like being safe or platform independent. But it has one dra...]]></description><link>https://blog.illucrum.com/java-hot-code-reloader</link><guid isPermaLink="true">https://blog.illucrum.com/java-hot-code-reloader</guid><category><![CDATA[Java]]></category><category><![CDATA[classloader]]></category><category><![CDATA[jvm]]></category><category><![CDATA[bytecode]]></category><dc:creator><![CDATA[Szymon Kokot]]></dc:creator><pubDate>Thu, 11 Dec 2025 08:00:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765311279922/018304a2-fb72-49fe-93b2-b905fa6e9960.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Without a doubt, Java is a wonderful language. It's fast, strongly typed, has C-like syntax, basically everything I like in a programming language. And also it has some other useful features like being safe or platform independent. But it has one drawback. And it is that every small change in code needs a application restart to take effect. This can be quite frustrating.</p>
<p>Of course, it isn't true for all projects, because this issue can be solved using different tools. But all of them have one thing in common, they use some kind of trick. The aim of this article is to explore the problem of hot code reloading in Java, and explain some possible solutions, including the one I used in my own project: the <a target="_blank" href="https://github.com/Illucrum-LLC/JHCR/releases"><strong>Java Hot Code Reloader</strong></a>.</p>
<hr />
<h2 id="heading-class-loading"><strong>Class loading</strong></h2>
<p>How are classes normally loaded by the JVM? This is quite simple, class loaders are used. The class loaders in the JVM are a separate very interesting subject, worth of exploring on its own. Here we will only rapidly go through the basics we need.</p>
<h3 id="heading-can-classes-get-loaded-twice"><strong>Can classes get loaded twice?</strong></h3>
<p>First, it's good to know that each class, can't be loaded twice by the same class loader, but it can be loaded twice by two different class loaders. Loaded classes are not identified internally only by their names, but also by the class loader that defined them.</p>
<h3 id="heading-class-loader-hierarchy"><strong>Class loader hierarchy</strong></h3>
<p>In a normal Java application, there are three class loaders:</p>
<ol>
<li><p><strong>Bootstrap loader:</strong> first class loader; represented by <code>null</code>, it is not accessible in any way from Java. It is used to get the absolute basic system loaded - essentially <code>java.base</code>.</p>
</li>
<li><p><strong>System loader:</strong> second class loader in the hierarchy, it can be accessed calling <code>ClassLoader.getSystemClassLoader()</code>. This loader loads the rest of the platform modules that the application depends upon. We can set a custom system class loader by running the java application with the <code>-Djava.system.class.loader=com.custom.CustomClassLoader</code> flag.</p>
</li>
<li><p><strong>Application loader:</strong> the last class loader in the standard hierarchy, it's the most widely used in the application.</p>
</li>
</ol>
<h3 id="heading-loading-a-class"><strong>Loading a class</strong></h3>
<p>When a class is to be loaded the loadClass method of a class loader is called. A correctly implemented loadClass method follow these steps:</p>
<ol>
<li><p>Calls findLoadedClass method. In the end, it's a native method, that searches if the target class has been loaded before. If it wasn't, we continue.</p>
</li>
<li><p>It calls the loadClass method of it's parent (the class loader immediately above in the hierarchy), to avoid loading the same class twice from different class loaders.</p>
</li>
<li><p>If the parent was unable to load the target class, the class loader calls its own findClass method, which attempts to find the target class. If it fails, the loader throws a ClassNotFoundException.</p>
</li>
</ol>
<h3 id="heading-how-the-loadclass-method-is-called"><strong>How the loadClass method is called?</strong></h3>
<p>The loadClass method can be called in two ways:</p>
<ol>
<li><p>It can be called manually, explicitely.</p>
</li>
<li><p>It can be called automatically by the JVM. But there's a catch. Remember the findLoadedClass method? Each class loader has it's own "cache", where all classes loaded by that class loader are saved. To save time. The JVM only calls the loadClass method only if it is unable to find the class in the class loaders cache.</p>
</li>
</ol>
<hr />
<h2 id="heading-instrumentation"><strong>Instrumentation</strong></h2>
<p>So, where is the problem? Well, the problem is that Java doesn't really allow overriding classes, unloading them so they can be loaded again, or loading the same class twice. An attentive reader may now say something like <em>"wait, didn't you say a class can be loaded twice by differnet class loaders?"</em>. And to you, dear reader, I answer: yes. Absolutely yes. I will explain this matter later on, in the "Some possible solutions" section.</p>
<p>Even though you can't reload classes, there is something Java gives you: Instrumentation. An what does Instrumentation give us?</p>
<h3 id="heading-redefinition"><strong>Redefinition</strong></h3>
<p>Instrumentation gives us redefinition. You can redefine classes, although there are limitations. The class structure needs to remain the same. No new methods, no removing methods, no renaming methods, non of the same to fields. It's a nice tool, but quite limited in a development environment.</p>
<h3 id="heading-transformers"><strong>Transformers</strong></h3>
<p>Transformers can be very useful too. They allow you to intercept the bytecode of a class before it is loaded or redefined. Having the bytecode, the content of a compiled class, you have full control over the class that is being loaded. You can change it's behavior, add custom methods, or even create a completely new class from scratch.</p>
<hr />
<h2 id="heading-some-possible-solutions"><strong>Some possible solutions</strong></h2>
<p>So it's quite clear now, that Java offers a very well designed environment, that works very well with a normal setup. But it doesn't really allow reloading classes. It allows redefinition, but that is not enough. So, what tricks can be used to solve this?</p>
<h3 id="heading-custom-jvm"><strong>Custom JVM</strong></h3>
<p>First let's mention the obvious one. Which basically is, you don't like how Java works? Just create you own version tailored specially for you! Easy, right? You don't have to create a whole new language from scratch, just replace a small part of its environment, one of the parts that makes Java so safe. After all, if it is to be used only in development, not in production, that's a perfectly valid solution. And it is used for example by <a target="_blank" href="https://dcevm.github.io/"><strong>DCEVM</strong></a>.</p>
<h3 id="heading-replacing-away-class-loaders"><strong>Replacing away class loaders</strong></h3>
<p>As promised, the complete answer to the attentive reader. Yes, you can load the same class (or different versions of the same class) by two differnt class loaders with no problems. But that would mean getting rid off your original class loader, and creating a new one which would have to load all classes all over again. After all, if you have a class A, that references another class B, you modify B and load it with another class loader, class A keeps referencing the class B loaded by the first class loader. So you have to load A again too, so it references the new version of B.</p>
<p>It is still a solution and it is actually used by some tools, like <a target="_blank" href="https://docs.spring.io/spring-boot/reference/using/devtools.html"><strong>Spring Boot DevTools</strong></a>.</p>
<h3 id="heading-jhcrs-solution"><strong>JHCRs solution</strong></h3>
<p>And what solution did I find? JHCR uses a double approach. At first, it tries using redefinition. When that is not possible, things get a little more interesting. First, lets see what elements are involved:</p>
<ol>
<li><p>Custom class loader</p>
</li>
<li><p>Custom cache memory to save already loaded classes</p>
</li>
<li><p>A transformer</p>
</li>
</ol>
<p>Now, lets say there is a Class A:</p>
<ol>
<li><p>Before loading any class, a transformer intercepts its bytecode, modifying it in a way, each call to a constructor of any class, explicitely calls the loadClass method of the custom class loader.</p>
</li>
<li><p>A hasn't been loaded before, so the loadClass method of my custom class loaders gets called normally.</p>
</li>
<li><p>It finds the class and saves it in a custom cache of the class loader (although there is no way of not saving the class in the default cache).</p>
</li>
<li><p>When the A class gets modified, a file watcher gets its new bytecode and changes the name of the new class version to A1.</p>
</li>
<li><p>Then the custom cache gets modified, so next time the loadClass method gets called for A, A1 is returned instead.</p>
</li>
<li><p>Because each constructor call has been modified forcing an explicit call to the loadClass method of our custom class loader, the default cache is never really used and from now on A1 is returned and instanced where needed instead of A.</p>
</li>
</ol>
<p>Of course, this way, changes to A do not apply for already existing instances of A, but it works like a charm for any new instances. And that is how the second version of the JHCR works.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Hot code reloading is not a trivial issue in Java. But it can be done using different tricks, and everyone comes with its own problems. This is what makes the this matter so interesting and complex. All the things that were briefly mentioned here, are definitely worth of investigating on their own: class loaders and delagation, the Instrumentation API, JVM internals, bytecode manipulation. And there are things that were not mentioned for the sake of simplicity, like reflection, which also plays an important part in making JHCR work.</p>
]]></content:encoded></item></channel></rss>