SEO-lessen uit het repareren van onze eigen site
We hebben een paar dagen onze eigen site gelezen zoals een zoekmachine dat doet, en zes zaken gevonden die het waard waren om te repareren. Elke pagina gaf twee FAQ-blokken aan, Google gebruikte een decoratieve achtergrondgloed als onze miniatuur, een reeks sjabloonpagina's rankte voor zoekopdrachten die ze niet beantwoordden, en een nieuw deel van de site werd op staging door onze eigen edge geblokkeerd. Niets daarvan was dramatisch. Alles kostte stilletjes zichtbaarheid.
De site in één alinea
mythex.ai is een single-page-app die we bij het bouwen vooraf renderen: een script loopt langs elke route, schrijft voor elke route een statisch HTML-bestand en voegt de titel, beschrijving en gestructureerde data van de pagina toe (het JSON-LD-blok dat zoekmachines vertelt wat een pagina is, zie wat gestructureerde data is). Het meeste van wat hierna komt, zit in die prerender-stap, omdat dat de HTML is die een crawler echt leest.
1. Elke pagina beweerde de FAQ-pagina te zijn
Symptoom. Ons HTML-sjabloon bevatte een sitebreed FAQPage-blok in de gestructureerde data, met een URL die naar /faq wees. Prerender voegde daar de eigen FAQPage van elke pagina bovenop toe. Dus elke pagina op de site leverde er twee, en ons privacybeleid vertelde Google dat het de FAQ-pagina was.
Waarom het ertoe doet. Google verwacht hooguit één FAQPage per pagina. Een tweede die naar elders wijst, is het soort fout waardoor de markup van een pagina wordt afgewaardeerd, niet alleen genegeerd.
Oplossing. Het globale blok is weg. De FAQ-markup van elke pagina komt nu uit één plek, ook die van /faq zelf, die hem bouwt uit de volledige lijst met vragen. Pagina's zonder FAQ's geven nu geen FAQ-markup meer, wat het eerlijke antwoord is. En prerender laat de build mislukken als een pagina ooit weer meer dan één FAQPage bevat. Een regel die alleen in iemands hoofd leeft, wordt geschonden; een regel die de build afdwingt, niet.
2. Google gebruikte het verkeerde plaatje voor ons
Symptoom. In zoekresultaten was de Mythex-miniatuur de zachte, pulserende gloed achter de hero van onze homepage, een decoratief achtergrondbeeld, in plaats van onze deelkaart.
Waarom het gebeurde. We hadden Google nooit verteld welk beeld een pagina vertegenwoordigt, dus koos het er zelf een.
Oplossing. Twee kanten van hetzelfde probleem:
- Zeg welk beeld van de pagina is. De homepage heeft nu een
WebPage-node met eenprimaryImageOfPagedat naar de deelkaart wijst, en de gestructureerde data van elke geprerenderde pagina bevat een eigen afbeelding (de deelafbeelding van de pagina, of de standaardafbeelding). - Verberg de decoratie. De achtergrondafbeeldingen zijn nu in
robots.txtniet toegestaan en worden met eennoindex, noimageindex-header geserveerd, zodat ze uit beeldzoekopdrachten en miniaturen blijven.
3. Zoekmachines kenden alleen ons logo
Onze Organization-markup had een naam, een logo en wat social links: branding, en verder niets. Zoekmachines bouwen het kennispaneel van een bedrijf op uit feiten zoals in een register, dus voegden we die toe uit onze handelsvergunning: de wettelijke naam, de oprichtingsdatum, de oprichter en het geregistreerde adres. Het telefoonnummer hebben we bewust weggelaten.
4. Sjabloonpagina's beantwoordden de verkeerde vraag
Symptoom. De Search Console liet zien dat drie sjabloonpagina's vertoningen kregen maar geen klikken. Eén rankte voor „content strategist portfolio” en varianten, één voor „best italian restaurant website design”, en één voor een cluster rond „agile board”. De helft van die zoekopdrachten bevatte het woord „free”. De posities liepen van het midden van de twintig tot in de vijftig.
Waarom. Elke pagina beantwoordde een andere vraag dan de gestelde. Iemand die wilde zien hoe goed Italiaans restaurantdesign eruitziet, kwam terecht op een pagina die hem een builder verkocht.
Oplossing. Elk van de drie heeft nu een sectie die voor de zoekopdracht is geschreven en niet voor het product, een titel en beschrijving in de woorden die mensen typen, en FAQ's die de markup waard zijn die ze al uitstuurden.
Dezelfde commit repareerde een stiller probleem. Het blok „gerelateerde sjablonen” nam de eerste vier sjablonen van een categorie, waardoor elke portfoliosjabloon naar dezelfde vier portfolio's verwees en de rest van die categorie helemaal geen interne links had. We vervingen het door een ring die op subcategorie is gesorteerd: elke sjabloonpagina krijgt nu precies vier links in en vier links uit. De geprerenderde HTML print die links nu ook af; daarvoor bestonden ze alleen nadat JavaScript was uitgevoerd, wat een crawler misschien nooit doet.
5. Bing meteen laten weten dat er nieuwe pagina's zijn
Google negeert IndexNow, een protocol om zoekmachines te pingen wanneer een URL verandert. Bing, Yandex en Seznam gebruiken het, en de index van Bing is wat ChatGPT-zoek leest. Een AI-appbouwer die AI-assistenten niet kunnen vinden, is een bijzonder soort falen.
De voor de hand liggende aanpak, de hele sitemap bij elke deploy indienen, is de manier waarop een sleutel wordt gethrottled, en bij de meeste deploys verandert er niets waar een zoekmachine om geeft. Dus vergelijkt een script de sitemap die de site nu serveert met die net gebouwd, en dient alleen het verschil in.
Twee details maakten dat het werkte:
- Maak een snapshot voordat je deployt. De uitgangssituatie moet worden vastgelegd voordat de nieuwe build live gaat. Daarna is de „live” sitemap al de nieuwe en komt elk verschil leeg terug.
- Alleen nieuwe pagina's, voorlopig. Onze sitemap heeft geen
lastmod-datums, dus het script meldt nieuwe pagina's maar geen herschrijvingen. Elke URL met de builddatum stempelen zou de hele site bij elke deploy als gewijzigd markeren, precies de spam die we wilden vermijden.
Het draait alleen bij productiedeploys en laat de build nooit mislukken: tegen de tijd dat het draait, staat de site al live, en een ping naar een zoekmachine is geen rode deploy waard.
6. Onze eigen edge zei „niet gevonden”
Toen we de /ai-pagina's lanceerden (meer daarover in een landingspagina voor elk soort bedrijf), toonde staging voor al die pagina's „Not found”, terwijl de statische host ze prima serveerde.
De dienst voor onze marketinghosts stuurt alleen een allowlist van paden door; al het andere krijgt een harde 404. /ai was nieuw en stond niet op de lijst. We hebben /ai en /ai/* toegevoegd, met een test die bevestigt dat ze doorkomen. Een kleine bug, maar precies het soort dat een nieuwe sectie onzichtbaar maakt voor crawlers, zonder dat iemand het merkt.
Wat we eruit haalden
- Lees de HTML die een crawler leest. Het meeste was onzichtbaar in een browser en duidelijk in het geprerenderde bestand.
- Maak van SEO-regels build-controles. „Eén FAQPage per pagina” wordt nu afgedwongen, niet onthouden.
- Vertel zoekmachines wat je bedoelt. Als je niet zegt welk beeld of welke feiten je vertegenwoordigen, zullen ze raden.
- De Search Console vertelt welke vraag mensen stelden. Vertoningen zonder klikken betekenen meestal dat de pagina een andere vraag beantwoordde.
- Dien verschillen in, niet alles. Alleen pingen wat is veranderd houdt je binnen de rate limits.
Als je hetzelfde doet voor een site die je zelf hebt gebouwd, dekken onze gidsen over SEO voor met AI gebouwde websites en de Google Search Console instellen de basis.