Your Inline CSS Is Making Pages Look Identical to Googlebot
On this page
Inline CSS doesn’t make two articles identical in Google’s eyes. Google’s canonicalization documentation says that when it finds multiple pages that seem to be the same, or whose primary content is very similar, it clusters them together and picks one as canonical. Styling isn’t primary content. A block of inlined critical CSS repeated on every page is no more a reason for Google to cluster them than a shared header is. When distinct articles end up in a duplicate cluster, there are two main explanations to check: Google never saw what makes them distinct, or their primary content is close to the same.
What Google compares
The canonicalization documentation gives an example that shows where the line is. Language versions of a page count as duplicates only if the primary content is in the same language. If only the header, footer and other non-critical text is translated and the body stays the same, the pages are duplicates. In that example, the comparison runs on the body, not on the parts every page shares.
It also matters which HTML Google looks at. Google’s JavaScript SEO basics says Googlebot queues pages for rendering and that Google also uses the rendered HTML to index the page. So the question is what the rendered page contains. If rendering produced the full article, a shared stylesheet doesn’t turn it into a copy of another article. If rendering produced only the template, the articles can come out alike, with or without the stylesheet.
How distinct pages end up looking the same
Several documented behaviors can leave Google with a rendered page that holds only the shared template:
- The app shell model. Google’s JavaScript guide describes sites where the initial HTML doesn’t contain the actual content, and Google has to execute JavaScript before it can see the content. If that JavaScript fails for Googlebot, the shell is all that’s left, and every article’s shell is the same.
- Blocked resources. Google Search won’t render JavaScript from blocked files or on blocked pages. If robots.txt blocks the script bundle, or the API endpoint the script calls for the article body, the render has nothing to fill the template with.
- Stale cached files. Googlebot caches aggressively, and Google says its rendering service may ignore caching headers and use outdated JavaScript or CSS. A cached old bundle that no longer matches your API can fail to load the body. Google recommends content fingerprinting in file names, such as
main.2bb85551.js, so that each update gets a new file name. - Content that loads on interaction. Google’s mobile-first indexing guidance says Google won’t load content that requires user interactions to load. An article body that appears only after a click is not in the rendered page.
And one explanation has nothing to do with rendering: templated pages whose primary content differs by a handful of words are similar, and Google can cluster them for that reason.
Diagnose with the page Google received
Take two articles that Search Console lists as duplicates of each other and open each in the URL Inspection tool.
- Check the canonical Google chose. Inspection shows the user-declared canonical and the Google-selected canonical.
- Run a live test and click View tested page. Google says this shows a screenshot of the rendered page, the HTML returned, the HTTP headers, the JavaScript console output and the page resources loaded.
- Read the HTML for the article body. If the two articles’ tested HTML both contain the template and an empty content container, Google isn’t seeing what makes them distinct.
- Read the console and the resources. JavaScript errors and resources that failed to load, including ones blocked by robots.txt, are where to look for the missing body.
- Compare with the raw source. View the page source, or fetch it with a command-line tool, to see what the server sends before scripts run. If the article body is missing there and present only in your browser, the content depends entirely on client-side JavaScript. That exposes it to failures such as a failed app shell, blocked resources, stale cached files and content that waits for a click.
Then read the reason in the Page indexing report the way Google defines it:
- “Duplicate without user-selected canonical” means the page is a duplicate of another, doesn’t declare a canonical, and Google chose the other page. Google’s advice is to mark the canonical explicitly if Google chose the wrong URL, or to make sure the content differs substantially if the page isn’t a duplicate.
- “Duplicate, Google chose different canonical than user” means you declared this page canonical but Google thinks another URL is a better canonical. Google notes that a duplicate page must be similar to its canonical. If the declared canonical isn’t similar to the current page, Google won’t choose it.
Put the unique content in the server response
When the failure is in rendering, the fix is to send the content that makes each page unique, the headline and the body, in the HTML the server returns, instead of fetching it with client-side JavaScript after load. Google’s JavaScript guide recommends server-side rendering or pre-rendering because it makes a site faster for users and crawlers, and because not all bots can run JavaScript. In a React or similar stack, that means rendering the article on the server or at build time. The component names depend on your framework and version.
The rule is narrow. Only the content that makes the page unique needs to be in the first response. Comments, related-post widgets, below-the-fold images and other secondary parts can stay deferred.
Alongside that:
- Unblock what rendering needs. Make sure robots.txt doesn’t block the scripts or API calls that build the page.
- Fingerprint your static files, so Google’s renderer doesn’t run an old bundle against new data.
- Don’t put
noindexin the original page code if you want the page indexed. Google’s JavaScript guide says that when Google seesnoindexin the initial HTML it may skip rendering. Removing the tag with JavaScript may not work. - Declare a self-referencing canonical on each article, so that Google has your preference alongside the content.
Critical CSS stays
Inlining critical CSS is a performance technique, and none of these fixes requires removing it. Google’s documentation on duplicates talks about primary content, not styling, and it gives no CSS threshold to stay under. Once each page’s HTML carries its own article, the shared styles are what they were before: the same wrapper around different content.
Frequently asked questions
Can identical inline CSS make Google treat pages as duplicates?
Not on its own. Google clusters pages whose primary content is the same or very similar. Shared CSS, like a shared header, isn’t primary content. If distinct articles are clustered, check whether Google’s rendered page contains their bodies.
Doesn’t Google render JavaScript anyway?
It does. Google says it uses the rendered HTML to index pages. But rendering can come back without your content: blocked scripts, errors in the renderer, stale cached files, or content that waits for a click. Putting the unique content in the server response removes those dependencies.
How do I see what Google saw?
Use URL Inspection. For the indexed version, open View crawled page. For what Google gets now, run a live test and click View tested page: it shows the rendered screenshot, the returned HTML, the JavaScript console and the page resources, which is where a missing body or a blocked file shows up.
Do I need to server-render the whole page?
No. Only the content that makes the page unique, the headline and the body, needs to be in the first response. Secondary elements can load later.