SEO for enkeltsideapplikasjoner: hvorfor SPA-er ikke rangerer, hvordan SSR, statisk generering og forhåndsrendering løser det, og hvordan du gjør appen lesbar for AI-crawlere.

På denne siden
Kort fortalt
en enkeltsideapplikasjon (SPA) laster ett HTML-skall og bygger hver visning med JavaScript i nettleseren. Google kan kjøre JavaScript, men rendering skjer forsinket og er skjør, og crawlerne bak ChatGPT, Claude og Perplexity kjører den ikke i det hele tatt. For å rangere og bli sitert må hver visning i en SPA ha sin egen URL, en ekte lenke med en href, en unik tittel og beskrivelse, en riktig statuskode og, framfor alt, hovedinnholdet tilstede i HTML-en serveren sender, gjennom rendering på server, statisk generering eller forhåndsrendering.
Vil du vite mer? Spør
Rask quiz
Hvem bør fikse den tekniske siden av nettstedet ditt?
Vårt råd til deg
Gi hver visning en ren URL som crawlere kan finne er den rette løsningen for deg
Nummer 1 i denne rangeringen, det beste valget etter svarene dine.
Vårt råd til deg
Bruk ekte lenker er den rette løsningen for deg
Nummer 2 i denne rangeringen, det beste valget etter svarene dine.
Vårt råd til deg
Oppdater tittel, beskrivelse og kanonisk URL per rute er den rette løsningen for deg
Nummer 3 i denne rangeringen, det beste valget etter svarene dine.
Vårt råd til deg
Returner ærlige statuskoder er den rette løsningen for deg
Nummer 4 i denne rangeringen, det beste valget etter svarene dine.
SEO for enkeltsideapplikasjoner er settet med teknikker som gjør en JavaScript-app bygget med React, Vue, Angular eller Svelte like lett å crawle som et klassisk nettsted. Problemet er godt dokumentert: Google forklarer i sitt grunnleggende om SEO for JavaScript at den behandler JavaScript-sider i tre faser (crawling, rendering, indeksering), og hver svakhet i en SPA ligger et sted i den rørledningen. Denne guiden fokuserer på SPA-er; for JavaScript-nettsteder generelt, les vår guide til SEO for JavaScript.
Et tradisjonelt nettsted returnerer et komplett HTML-dokument for hver URL. En SPA returnerer nesten det samme dokumentet for hver URL: en tom <div id="root">, noen metataggar og en stor JavaScript-pakke. Nettleseren laster ned pakken, kaller et API, og tegner så siden. Når besøkende klikker på en lenke, bytter JavaScript ut innholdet uten å laste siden på nytt.
For et menneske med en rask telefon føles resultatet øyeblikkelig. For en crawler er første svar et tomt skall: ingen overskrift, ingen tekst, ingen lenker. Alt avhenger av om roboten kjører JavaScript-en, og når. Den ene faktaen forklarer de fleste SEO-problemene i SPA-er:
/#/pricing), og delen etter # sendes aldri til serveren, så alle visninger faller sammen til én URL.<title>, og hvis ruteren ikke oppdaterer den, deler alle sidene den.href: knapper og onClick-behandlere navigerer for brukere, men gir crawlere ingenting å følge.Googlebot henter først den rå HTML-en og leser lenkene og direktivene den finner der. Sider som returnerer statuskode 200, legges deretter i kø for Web Rendering Service, en headless Chromium. Google sier at en side «kan bli stående i denne køen i noen sekunder, men det kan ta lengre tid». Når siden er rendret, analyseres den resulterende HTML-en på nytt for innhold og lenker, og deretter indekseres den.
Fire detaljer fra Googles dokumentasjon betyr noe for SPA-er:
<a>-elementer med en href er pålitelige lenker. Lenker som JavaScript setter inn, er greie så lenge de følger det formatet.pushState) i stedet for #-ruter. Google utfasa sin gamle AJAX-crawlingordning (#!-URL-ene) i oktober 2015.noindex i den opprinnelige HTML-en vinner. Google kan hoppe over rendering når den ser noindex, så det hjelper ikke å fjerne den med JavaScript senere.Den praktiske konsekvensen: Google kan indeksere en SPA med rendering i klienten, men du legger til et andre steg, en forsinkelse og et feilpunkt på hver side. En tidsavbrudd, et blokkert API-kall eller en JavaScript-feil under rendering etterlater den indekserte versjonen tom. Sjekk hva Google ser med URL-inspeksjonsverktøyet i Search Console, og les vår guide om hvordan indeksering hos Google fungerer hvis sider blir værende utenfor indeksen.
Stort sett ikke. I en studie publisert i desember 2024 om trafikken i sitt nettverk fant Vercel og MERJ at «ingen av de store AI-crawlerne rendrer JavaScript i dag»: GPTBot, OAI-SearchBot og ChatGPT-User (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Meta-ExternalAgent og Bytespider leser alle bare den rå HTML-en. De laster ned JavaScript-filer (rundt 11.5% av ChatGPTs forespørsler og 23.8% av Claudes), men kjører dem ikke. Unntakene er Gemini, som bruker Googles renderingsinfrastruktur, og AppleBot, som bruker en nettleserbasert crawler.
For en SPA med rendering i klienten betyr det at AI-crawlerne som mater ChatGPT, Claude og Perplexity ser en tom side. Produktet ditt kan rangere på Google og likevel være usynlig i KI-svar, fordi assistenten aldri leste et ord av det. Det samme gjelder de fleste lenkeforhåndsvisningsrobotene i sosiale nettverk og meldingsapper, som leser Open Graph-taggene i den rå HTML-en. Når innholdet står i HTML-en, bør du også sjekke at din robots.txt slipper til AI-crawlerne du ønsker.
Løsningen er å sende ekte HTML i første svar. Google kaller dynamisk rendering (å servere en forhåndsrendret versjon bare til roboter) «en omvei og ikke en anbefalt løsning» i sin dokumentasjon om dynamisk rendering, og peker i stedet på rendering på server, statisk rendering eller hydrering. Definisjonene nedenfor følger referansen Rendering på nettet på web.dev.
| Strategi | Hvordan den fungerer | Innhold i første HTML | Best for | Begrensninger |
|---|---|---|---|---|
| Rendering i klienten (CSR) | Nettleseren bygger siden fra JavaScript og et API | Nei | Dashbord og sider bak innlogging | Forsinket indeksering på Google, usynlig for de fleste AI-crawlere |
| Rendering på server (SSR) | Serveren rendrer HTML ved hver forespørsel, og deretter hydrerer JavaScript den | Ja | Kataloger, oppføringer, innhold som endrer seg ofte eller er personalisert | Serverkostnad, tregere svar hvis det ikke er bufret |
| Statisk generering (SSG) | HTML genereres ved bygging for hver URL og serveres fra et CDN | Ja | Markedsføringssider, blogg, dokumentasjon, landingssider | Ny bygging må til når innholdet endres (det finnes inkrementelle alternativer) |
| Forhåndsrendering ved bygging | En headless nettleser fanger opp den første tilstanden til hver rute som statisk HTML | Ja | Eksisterende SPA-er med et begrenset antall offentlige ruter | Data fryst ved bygging, ruter må listes opp |
| Dynamisk rendering | Roboter får et forhåndsrendret øyeblikksbilde, brukere får SPA-en | Ja, bare for oppførte roboter | Midlertidig løsning for en eldre app | Offisielt en omvei, vedlikeholdskostnad, risiko for at roboter får annet innhold |
De fleste moderne rammeverk lar deg blande strategier per rute: statisk for markedsføringssider, rendret på server for katalogen, rendret i klienten for den innloggede appen. Dette hybride oppsettet gir crawlere full HTML der søketrafikken er, og beholder SPA-opplevelsen der den tilfører verdi.
| Bibliotek | Rammeverk eller funksjon for HTML ved første lasting |
|---|---|
| React | Next.js (serverkomponenter, SSR og statisk generering), React Router i rammeverksmodus, Gatsby |
| Vue | Nuxt (universell rendering som standard, statisk generering tilgjengelig) |
| Angular | Angular SSR (rendering på server og forhåndsrendering ved bygging) |
| Svelte | SvelteKit (rendering på server som standard, forhåndsrendering per rute) |
| Alle disse | Astro (statisk HTML som standard, interaktive øyer lastes bare der det trengs) |
Nettsteder generert av AI-nettstedsbyggere fortjener en spesiell nevnelse: mange eksporterer en React-app som rendres i klienten. Hvis du har bygget nettstedet ditt med en slik, se våre notater om SEO og GEO for Lovable før du antar at Google og ChatGPT kan lese det.
Bruk History API (/pricing, aldri /#/pricing), én URL per stykke innhold, og den samme URL-en enten besøkende kommer direkte eller via navigasjon i appen. Hver URL må laste riktig innhold når den åpnes i en ny fane, som er testen en crawler gjør.
Hvert navigasjonselement som fører til en indekserbar side, bør være en <a href="/path">. Lenkekomponentene i rammeverkene (Link, NuxtLink, routerLink) gir denne markeringen; egne klikkbehandlere på div- eller button-elementer gjør ikke det. Gode lenker bærer også nettstedsarkitekturen din: hvis en side ikke er lenket, finner crawlere den sjelden.
Hver rute trenger sin egen tittel, metabeskrivelse, kanonisk URL og Open Graph-tagger, generert på serveren når det er mulig. Vår side om metatagger lister hva du bør sette. Behold én kanonisk tagg: Google anbefaler å sette den i HTML-en, og hvis JavaScript endrer den, må resultatet ikke motsi originalen.
Manglende produkter og slettede artikler må ikke svare 200 med en feilmelding. Med SSR returnerer du en ekte 404 eller 410 fra serveren. I en ren SPA godtar Google to reserveløsninger: omdirigere med JavaScript til en URL som gir en 404, eller legge til en noindex-robotmetatagg på feilvisningen.
Overskrifter, brødtekst, priser, FAQ og JSON-LD-strukturerte data bør stå i serverresponsen, ikke lastes etter et klikk eller en rulling. Innhold bak faner som rendres på forespørsel, eller bak knapper for «last inn flere», blir ofte oversett.
Del pakken opp per rute, utsett det som ikke trengs for den første visningen, og unngå å rendre hele siden på nytt under hydrering. Merk at felt-data fra Chrome (CrUX) tilskriver målingene av navigasjoner i appen til URL-en besøkeren først lastet, så test de viktigste malene dine hver for seg.
Sammenlign tre versjoner av hver viktig mal: den rå HTML-en (vis kilden, eller hent siden med et kommandolinjeverktøy), Googles rendrede HTML (URL-inspeksjon, deretter «Vis gjennomsøkt side») og siden med JavaScript slått av. Hvis hovedteksten bare dukker opp i den andre versjonen, ser ikke AI-crawlerne den. Vår gratis revisjon av gjennomsøkbarhet for AI og sjekkeren for indekserbarhet kjører disse testene på en hvilken som helst URL.
| Symptom | Sannsynlig årsak | Løsning |
|---|---|---|
| Search Console viser mange sider som «Gjennomsøkt, foreløpig ikke indeksert» | Tom eller nesten identisk HTML før rendering | SSR, SSG eller forhåndsrendering for offentlige ruter |
Alle resultatene i et site:-søk viser samme tittel | Tittel ikke oppdatert per rute | Håndtering av hode per rute på serveren |
| Bare forsiden er indeksert | Ruting med fragmenter eller lenker uten href | History API og ekte <a>-lenker |
| Feilsider dukker opp i indeksen | Myke 404-feil (statuskode 200 overalt) | 404 fra serveren, JavaScript-omdirigering til en 404-URL, eller noindex |
| Rangerer på Google, men blir aldri sitert av ChatGPT eller Perplexity | Innhold som bare er synlig etter JavaScript-kjøring | Innhold i det første HTML-svaret |
| Gammelt innhold vises i Googles rendrede visning | Bufrede JavaScript- eller CSS-filer | Filnavn med fingeravtrykk |
I årevis var rendering i klienten en håndterbar risiko, fordi Google til slutt rendret JavaScript. Nå som en del av oppdagelsen skjer i ChatGPT, Claude, Gemini og Perplexity, har kostnaden endret seg: en side som bare finnes etter JavaScript-kjøring, mangler i kildene de fleste assistentene kan lese. Gjennomsøkbarhet i den rå HTML-en har blitt det første kravet for generativ motoroptimalisering.
Når HTML-en er komplett, følger resten de vanlige reglene: sider som svarer tydelig på ett spørsmål, med kildebelagte fakta og strukturerte data, er de assistentene siterer. GEO-optimalisering fra Sorank hjelper deg å skrive og publisere det innholdet, og sporing av AI-omtaler viser om ChatGPT, Claude og Gemini siterer merket ditt etter rendringsfiksen.
Hovedregelen for SEO for enkeltsideapplikasjoner får plass i én setning: alt du vil at Google skal rangere og AI skal sitere, må stå i HTML-en serveren sender. Behold SPA-en for den innloggede opplevelsen, render offentlige sider på serveren eller ved bygging, og test deretter hva roboter får før og etter hver utgivelse.
En enkeltsideapplikasjon blir ikke straffet av Google, men oppsettet som er standard, rendering i klienten med ett HTML-skall, gjør indeksering tregere og mindre pålitelig. De fleste AI-crawlere kjører ikke JavaScript, så de ser en tom side. Med rendering på server, statisk generering eller forhåndsrendering på offentlige ruter kan en SPA rangere like godt som et klassisk nettsted.
React i seg selv er nøytral: det som betyr noe, er hvor HTML-en lages. En React-app som bare rendres i nettleseren, har de vanlige SPA-problemene, mens de samme komponentene rendret på server med Next.js eller React Router i rammeverksmodus leverer komplett HTML til crawlere. Velg et rammeverk som støtter rendering på server eller statisk rendering for sidene du vil ha indeksert.
Bare som en midlertidig løsning. Google beskriver dynamisk rendering som en omvei og ikke en anbefalt løsning, fordi det koster og medfører risiko å vedlikeholde en egen versjon for roboter. Rendering på server, statisk generering eller forhåndsrendering ved bygging gir samme HTML til alle besøkende, og er de langsiktige løsningene.
DE PRØVDE SORANK FØR DEG
