Skip to content
megapromotingLet's talk

Expertise · SEO

Optimisation for classic search engines: we go through each address, put the result into a table and fix what can be verified.

Technical and structural SEO — indexability, canonical URLs, sitemap generated from data, redirects, titles and descriptions, thin content, speed measured in bytes. No promises of rankings.

Already builtTwo in-house implementations, both open on disk. First: the audit of this site — 249 addresses crawled with direct requests, 23 columns per address, the result in a versioned tabular file alongside the code, plus the fixes that came out of it (the canonical address resolved once for all routes, the sharing address, the site map generated from data). Second: `mega-seo-analyzer`, an in-house analyser with 16 analysis modules and a weighted score written explicitly in code. What we cannot claim and will not write: positions obtained or growth percentages. We do not have publishable measurements for such things.

Classic SEO is an inventory job, not an ideas job. A search engine must be able to reach every page, understand which is its official version, receive a title and description that do not repeat, and find enough content to deserve a place in a list. Almost everything that breaks here can be counted, and what can be counted can be fixed.

That is why we start with a full crawl, not a sample. On this site that produced 249 addresses, each with 23 columns: response code, canonical address, title, description, hreflang, number of structured data blocks, amount of visible text and the rest. The result is a versioned tabular file next to the code, so every statement below can be reproduced with the commands in the report appendix.

What came out: 244 addresses respond 200 and five redirect. 131 pages did not have a canonical address. 219 of 244 declared the home page as the share address, so any sharing showed the wrong page. 100 titles exceeded 60 characters, the longest having 106. 65 pages shared a single template-generated description. 96 pages had under 2,000 characters of visible text. The first two were fixed with one line each in the base layout, which applies to every route; the rest are in the work list, with written priority.

This page is one of three. SEO deals with the engines that return a list of links. Visibility in model-generated answers is something else and has its own page, because it is controlled differently and — importantly — cannot be promised. Direct answers and structured data are the third. What is common to all three: the page must be accessible, server-rendered and have a single official address. That part is done once and serves all.

What it covers

The work, by component

We crawl each address, not a sample

Direct requests to every known address, without following redirects, with at most six concurrent requests so as not to disturb the server, and 23 columns per address: code, canonical address, title, description, hreflang, number of structured data blocks, amount of visible text. The result is a tabular file we hand over. On this site: 249 addresses, of which 244 respond 200 and 5 redirect.

The official address of a page, resolved once for the entire site

131 pages declared no canonical address, and 219 of 244 declared the home page as the share address — so any sharing on social networks showed a different page. Both were fixed with a relative declaration in the base layout, which resolves for each route separately. It is one line of code instead of a convention each new page would have had to remember on its own.

Sitemap generated from data, checked after publication

The sitemap is built from the content sources and goes through a final deduplication — on this site, 147 addresses, the same number in the code and in the production-served file. A script run after publication fails if the sitemap loses a page or if address variants appear that do not open. What is missing today, stated as missing: the entries do not carry a last-modified date, and 93 indexable addresses are not yet included.

Old addresses each get a decision

In a restructure, every existing address gets a verdict: stays, redirects permanently or disappears. On this site, 43 redirects resulted in the configuration. Verified separately are the things nobody tests: the jump from the domain without `www` to the one with `www` is a single one; the address with a trailing slash redirects correctly; the address written in uppercase returns 404, so there is no writing duplicate.

Titles, descriptions and thin content, counted

100 titles out of 244 exceed 60 characters, the longest having 106 — the risk is truncation in results. 33 descriptions exceed 160 characters, but zero are missing. More serious: 65 pages share a single template-generated description, and 30 of them differ between them by 240 bytes in total. Median visible text: 2,328 characters, with 96 pages under 2,000. These are numbers, not impressions, and each has a list of addresses behind it.

An in-house analyser, with modules and weights written in code

Our analyser has 16 modules — on-page, performance, sitemap, security, accessibility, name infrastructure, domain registration information, external links, social networks, technical stack, positions, keyword research, general audit — plus comparison modules: competitor finding, keyword gap, content gap, benchmarks. The overall score is explicitly weighted in code: performance 0.20, SEO 0.20, on-page 0.15, security 0.15, direct responses 0.10, accessibility 0.10, social 0.10. Modules that fail do not drag the score down — they fall out of the weighting, so a failed external service does not produce a false report.

Redirects that do not cost a whole page

A redirect made from inside the application builds the page and only then sends the redirect response. On this site there are 11 such cases, each producing over 200 KB of HTML before saying “go elsewhere”. It works, but it is wasteful; moving them into configuration is a small job with a direct effect on the crawl budget. It is on the fixes list, written as missing.

What a crawler sees, checked with the crawler, not assumed

We requested five addresses with 18 different user-agent identifiers and compared the code, size and fingerprint of the normalised content. All receive 200 and exactly the same content as a browser; `robots.txt` is identical, 129 bytes, for all; there is no blocking, challenge or rate limiting for crawlers. The only reproducible difference — 237 bytes less on one dynamic page, for three agents — comes from the framework itself, which sends them full unstreamed HTML, therefore more ready-rendered content, not less.

What we do not promise, written before the contract

We do not promise positions, growth percentages or a number of visits. We do not have publishable measurements for that and we do not invent them. What we deliver is verifiable in another way: the list of addresses with each one’s status, the fixes made, the check run after publication and the measurable difference between the before and after state — in bytes, codes and page counts, not in promises.

What it looks like

The path, step by step.

01

Full crawl and status table

The first delivery is the spreadsheet file with every address and its status across 23 columns, plus the commands that reproduce it. From here on, any discussion has a row behind it. It is also the moment when the addresses that no one knew existed are discovered.

02

Structural fixes, in order of impact

First the things that are fixed in one place and applied everywhere: the canonical address, the sharing address, the error page behaviour, the rules for robots. Then the ones that require work on the page: titles, descriptions, thin content. The order is not negotiable — otherwise, you repair a hundred pages manually for something that was solved with one line.

03

Sitemap and redirects

The sitemap is linked to the data sources, so a new page goes in by itself. Old addresses get permanent redirects in configuration, not inside the application. We deliver the full list of decisions, address by address.

04

The check that stays after us

We deliver a script run after every publication, which fails if a canonical address has disappeared, if the sitemap has lost a page or if `robots.txt` has started blocking rendering resources. Without it, fixes erode within a few months and no one notices until the next audit.

05

Measurement, with your tools

If you have Search Console and an analytics tool, we build reporting over them and set what we track. If you do not have them, the first step is to have them — and we say that beforehand, not afterwards. What we do not do: we do not report positions from a third-party tool as if they were source data.

The website as territory, checks as layers over it1response code2canonical address3title and description4date structurate5text volume249 addresses, 23 columns, one spreadsheet file.
The website as territory, checks as layers over it

The data

What we touch, where it lives, and how long it stays

The questions anyone with a data protection officer would ask — asked here before they do.

What we read from your site
Only what is public: the HTML of the pages, response headers, `robots.txt`, the sitemap. Direct requests, at a limited rate — at most six in parallel, so crawling does not look like an attack. We do not need administration access for the audit part.
What we need from you, if you also want the measurement part
Read access to the search console and the traffic analysis tool. Without them we can say what is technically wrong, but not what is happening in the results. The audit of this site was deliberately carried out without such access, and the limitation is explicitly stated in the document — so that no one confuses a technical measurement with a traffic one.
Where the results are stored
The spreadsheet with the crawl and the written report are kept in the project repository, versioned alongside the code. Not in a presentation and not in a subscription tool you cannot extract them from. When a figure changes, the file history shows who changed it and when.
Report retention
They live as long as the project repository lives. The crawled data are public by definition — they are your pages, as anyone sees them. If the audit touches areas that require authentication, what is saved and for how long is agreed separately.

A case

249 addresses, 23 columns, and two lines of code that fixed 350 pages

The situation

A recently restructured site, with approximately 250 public addresses. All returned 200 and nothing seemed wrong. The starting question was not “how do we grow traffic”, but “what does each page declare about itself”.

What we built

We crawled every address with direct requests, without following redirects, with at most six concurrent requests, and wrote 23 columns for each in a spreadsheet versioned alongside the code. On top of it we ran separate checks: who declares which canonical address, who declares which sharing address, what lengths the titles and descriptions have, how many pages share the same template description, how much visible text each has, what the server returns to 18 different user-agent identifiers, what it offers for compression and protocol. Every figure was read from the actual response, not inferred from configuration.

What came out

244 addresses return 200, five redirect. 131 pages did not declare a canonical address; 219 out of 244 declared the homepage as the sharing address. Both were fixed with one relative declaration each in the base layout — two lines that apply to every route, instead of a correction on every page. The remaining findings went into an eleven-step plan, in order of impact: 100 titles over 60 characters, 65 pages with a template description, 96 pages with under 2,000 characters of text, 93 indexable addresses missing from the sitemap, 11 redirects made from inside the application.

What the case does not say

The audit was done without access to the search console and without traffic data, deliberately, and the limitation is written in the report: we can say what is technically wrong, not what is happening in the results. Of the eleven steps in the plan, two are applied today; the rest are open work, not ticked off. A report that declares all steps completed on the day they were written is not a report.

Questions

What people ask us before they call

What is the difference between SEO, GEO and AEO, briefly?

The audience is different. SEO addresses engines that return a list of links — your page appears, the person clicks. GEO addresses generative models that compose an answer and may cite a source; there is no position there and no guarantee, so work is done on what can be controlled, not on the result. AEO addresses direct answers — the featured snippet, the information panel, the voice response — and relies on correct structured data. The basis is common: an accessible page, server-rendered, with a single official address. That part is done once.

What do you actually deliver in an SEO audit?

A spreadsheet with every address of the site and its status across 23 columns — response code, canonical address, title, description, hreflang, structured data blocks, text volume — plus a written report with the findings in order of impact, each with the code location, criterion and fix. And the commands that reproduce each figure. For this site, 249 rows came out; it is right in the repository, next to the code.

Do you guarantee first place?

No, and not any specific position either. We have no publishable measurements for results of that kind and we do not invent them. What we can show is the verifiable difference: how many pages had no canonical address before and how many do now, how many incorrectly declared the sharing address, how many old addresses were left without redirects. For this site the figures were 131, and respectively 219 out of 244. Those are facts; a promised position is not.

How do you know what you fix stays fixed?

From a script run after each publication, which checks canonical addresses, content anchors, the sitemap and `robots.txt`, and fails if something has disappeared. SEO fixes erode exactly like any other unwritten convention: someone adds a new page, forgets a declaration, and nobody notices until the next audit. A script notices immediately.

Do you have your own tools, or do you use subscriptions?

Both have their place, but we do the technical analysis with our own analyser: 16 modules — on-page, performance, sitemap, security, accessibility, name infrastructure, domain registration, external links, social networks, technical stack, rankings, keywords — plus comparison modules with competitors. The overall score has weights written in code, not hidden: performance and SEO 0.20 each, on-page and security 0.15 each, the rest 0.10 each. A module that fails drops out of the weighting instead of producing a false score.

What do you do with one hundred almost identical pages?

We flag them as a risk, not an opportunity. On this site, 100 of the 147 addresses in the sitemap are service × domain combinations, and 65 pages share a single template description — 30 of them differ from each other by a total of 240 bytes. A search engine treats this as content produced at scale, and the risk is a penalty, not extra visibility. The solution is real content on each page, or fewer pages. We do not recommend page generation as a strategy.

Does speed matter for SEO?

It matters, but not in the form it is usually sold. We do not give you a lab score, because it is easy to shift and does not say what a visitor experiences. We give you measured bytes: how much the compressed HTML weighs, what is sent on each navigation, what the JavaScript packages contain, whether the server offers modern compression and a new protocol. On this site: it does not offer either Brotli or HTTP/2, the translation catalogue costs approximately 70 KB compressed on each navigation, and a 443 KB package contains four language catalogues of which only one is used. All three are on the repair list.

Do you block AI crawlers?

It is the site owner’s decision, not ours, and it requires separating three categories that are treated identically on most sites today: search crawlers that send people back, agents triggered by a human who requested the page, and training crawlers. The rules for them are independent. On this site there is currently a single general rule, so the position is implicit — and we say so, instead of pretending it is a strategy. The details belong on the page about visibility in generated responses.

What do you not do?

We do not buy links and do not build site networks. We do not generate pages at scale to cover word combinations. We do not report rankings taken from a third-party tool as if they were source data. And we do not declare an audit complete without the spreadsheet file and the commands that reproduce it — a report you cannot verify yourself is not an audit, it is an opinion.

What the statements above rest on (14 sources)

14 of them are code and files from our repositories. We don't publish their name or line: together, on a single page, they would describe too precisely how systems that aren't only ours are built. We go through them with you, in the repository, on request — verification stays possible, it just happens in a conversation.

What would you want to work better?

Tell us about your process. Together we decide what is worth building, what we can connect, and how we check the result.

Let's talk