A site can look finished in a browser and still give search engines very little in the head of each page. In a client-side rendered app, the title, the canonical link and the status code are often set by script, or not set at all. One common result is the same title on every page.
We met this pattern on a rebuild: the previous Letters in Linen website was a client-side rendered app whose pages all carried one title. This article sets out what Google documents about titles, canonicals and status codes in that situation, and how to check what Google received. Where we give our own reading rather than Google’s wording, we say so. The build itself is described on its project page.
The symptom: one title across every page
Here is a hypothetical example. A shop built as a single-page app has forty product pages. Each shows its own product in the browser, but the title element in the HTML the server sends is identical on all of them, and any change to it happens after a script runs. Browser tabs, bookmarks and, depending on rendering, search results all show the same words.
Nothing looks broken, which is why the fault persists. It only appears when you compare pages, or when you look at what a crawler received rather than what a browser eventually displayed.
What Google asks for in a title
Google’s documentation on influencing title links asks that every page has a title specified in the <title> element, written as descriptive and concise text. It says to avoid vague descriptors such as “Home” for a home page, to avoid keyword stuffing, and to avoid repeated or boilerplate text, with distinct text describing the content of each page. Its own example is a commerce site whose pages all share one generic title, which it says makes it impossible for users to tell two pages apart.
It also says to brand titles concisely, with the site name at the start or the end separated by a delimiter, and to make clear which text is the main title of the page, ideally the first visible <h1>.
What Google does when a title is not good enough
The same page says title links are generated automatically, from several sources: the title element, the main visual title on the page, heading elements, og:title meta tags, other large and prominent text, anchor text on the page, text in links pointing to the page, and WebSite structured data. It lists common issues it adjusts for, including half-empty titles, inaccurate titles and micro-boilerplate, where a subset of pages repeats the same text. In those cases it may build a title link from other sources.
It adds that Google has to recrawl and reprocess a page to notice changes, which may take a few days to a few weeks. Our reading: a template fix can be correct on day one and still take time to show in results, so confirm it by looking at what was crawled, not at the results page.
What script is allowed to change
The JavaScript SEO basics page says Google processes JavaScript web apps in three phases: crawling, rendering and indexing. It says you can use JavaScript to set or change the meta description and the title element, and that unique, descriptive titles and snippets help users identify the best result.
Pages with a 200 status are queued for rendering unless a robots meta tag or header says not to index them. The page may wait in that queue for a few seconds, but it can take longer. The same documentation says server-side or pre-rendering is still a good idea, because it makes a site faster for users and crawlers and not all bots can run JavaScript. Our reading: if the title exists only after rendering, every page’s title depends on the render queue and on the script running without errors.
The canonical URL is treated more strictly. The documentation says the best way to set it is in HTML. You can use JavaScript, but you should not use it to change the canonical to something other than the URL specified in the original HTML. If a script injects the tag, it should be the only rel="canonical" tag on the page, because conflicting or multiple tags may lead to unexpected results.
Status codes when the server answers 200 for everything
Google’s JavaScript documentation says Googlebot uses HTTP status codes to find out whether something went wrong, and that a 404 should be used for a page that cannot be found. In a client-side app with client-side routing that can be impractical, and its troubleshooting guide names the risk: error pages that report a 200 status can be indexed and possibly shown in results. These are soft 404 errors.
It gives two strategies. One is a JavaScript redirect to a URL for which the server responds with a 404 status. The other is to add a noindex robots meta tag to error pages using JavaScript. It also notes that for non-200 status codes, rendering might be skipped.
Common traps in a client-side app
- Views that load by changing the part of the URL after a
#. Google says it cannot reliably resolve those URLs, and recommends the History API so each view has a real URL. - Error pages that answer 200, as above.
- More than one canonical tag, or a canonical that script rewrites to a different URL from the one in the HTML.
- Pages or files blocked in robots.txt. Google says it will not render JavaScript from blocked files or on blocked pages.
- Our reading: a title that is set late and only by script, so that the raw HTML a crawler first receives has none of the page’s real signals.
Checking the head of the page as Google received it
The Search Console URL Inspection tool lets you view the crawled page, which shows the HTTP request and response and the returned HTML, and a screenshot of how the page is seen. The more-information view lists loaded resources and JavaScript output. Google’s guide to fixing search-related JavaScript problems points to the same tool and to the Rich Results Test to check that the rendered HTML has the content you expect. The Page indexing section shows the Google-selected canonical, but only for the indexed version; the live test cannot predict which URL will be chosen.
A routine we would use, which is our reading rather than a Google procedure: take three or four pages of different types, and for each compare the title, the canonical and the status code in the raw HTML with the same three values in the rendered HTML. If they differ, or the raw title is the same everywhere, you know what to fix first.
Where this fits at Cultured Digital: rebuilds and rendering
This sits within technical SEO and, when the fix is a rebuild, within web development. Our rendering guide covers JavaScript SEO and rendered versus raw HTML, and our rebuilds and migrations guide covers rebuilds with a search-friendly architecture. The principles we state for builds are semantic HTML with real headings, and content in the HTML with JavaScript kept minimal.
The Letters in Linen rebuild followed those principles. Its project page describes the result: a title, description and canonical URL on every page, with the content served as HTML.
