The method and results come from our test in May and June 2018. The section What has changed since then describes where Google stands today.
- Google picks up a canonical set via JavaScript during rendering and recommends putting the canonical in the source code. If the source code already has one, JavaScript must not change it to a different URL.
- In May 2018, a Google talk still said canonicals in the rendered HTML were ignored. We checked. A script in Google Tag Manager added a canonical pointing to the blog overview on four category and author pages, only in the rendered HTML. Two similar pages stayed unchanged as a control group.
- Google canonicalized all four test pages, after 10, 23, 24 and 34 days. Search Console still showed the pages with a different status.
Why we ran the test
At Google I/O in May 2018 there was a talk on JavaScript SEO. It said that Google does not look for canonical tags in the rendered HTML. That did not match our test with Google Tag Manager from the year before, where a canonical added via Tag Manager had worked.
That earlier finding was based on a single URL, though. With canonicals, this is a known problem. A canonical only works between very similar pages, and Google often canonicalizes those even without a canonical. A single hit can therefore be chance. So the day after the talk we set up the test again, with more pages and a control group.
Our question was how Google treats websites that depend on client-side JavaScript. Whether you should set canonicals via JavaScript is a different question. The answer to that comes further down.
Test setup
On 11 May 2018, Google Tag Manager added a canonical pointing to the blog overview on four pages. The source code of these pages contained no canonical pointing to the overview. The script looked roughly like this.
| Page | Role | Status on 11 May 2018 |
|---|---|---|
| English category “SEO experiments” | Test, canonical to the blog overview | not canonicalized |
| English category “SEO for website relaunches” | Test, canonical to the blog overview | not canonicalized |
| German category “SEO für Website-Relaunches” | Test, canonical to the German blog overview | not canonicalized |
| German author page of Michael Weber | Test, canonical to the blog overview | already canonicalized by Google to the English author page (missing hreflang) |
| German author page of Eoghan Henn | Control, no canonical | – |
| English author page of Michael Weber | Control, no canonical | – |
The control pages were meant to show whether Google would merge such pages into the overview even without our canonical. If that had happened, the test would have proved nothing. At the time, we checked the status with the info: search query, which showed the URL Google had chosen.
Result
| Date | Days after insertion | Page canonicalized |
|---|---|---|
| 21 May 2018 | 10 | English category “SEO for website relaunches” |
| 3 June 2018 | 23 | English category “SEO experiments” |
| 4 June 2018 | 24 | German category, to the German blog overview |
| 13 June 2018 | 34 | German author page of Michael Weber |
All four test pages ended up on the target of the canonical added via JavaScript. As far as we know, none of these pages had ever been canonicalized that way before.
Requesting indexing barely helped
On 11 May we used “Fetch and render” with “Request indexing” in Search Console for all test pages. On 22 May we did the same for the blog overviews with all linked pages, and on 1 June once more for the three pages that had not been canonicalized by then. For new URLs this usually works almost immediately. Here the first request had no visible effect. The request on 1 June may have triggered the changes on 3 and 4 June. Perhaps Google also has to render a page several times before it picks up an inserted canonical.
Search Console showed something else
In the index coverage report of the time, the canonicalized test pages were listed as “Submitted URL not selected as canonical”. We would have expected “Alternate page with proper canonical tag”. Our explanation was that the report followed the official rules. It overlooked canonicals that only appear in the rendered HTML, even though Search used them.
Our conclusion
- Google used canonicals that only appeared in the rendered HTML, contrary to what the talk said.
- For some pages, it took more than three weeks for the canonical to be picked up.
- “Request indexing” did not noticeably speed up rendering.
- Search Console ignored the inserted canonicals in its reports.
- The statement in the talk may have been based on a misunderstanding or a mistake.
What has changed since then?
Google now describes this behavior itself. According to its JavaScript SEO documentation, Google Search picks up a canonical inserted via JavaScript during rendering. It is still not recommended. Google advises setting the canonical in the HTML. If you set it via JavaScript, it should name the same URL as the canonical in the source code. If that is not possible, leave it out of the source code. In the end, the page may only contain one canonical. According to Google, multiple or conflicting canonicals lead to unexpected results.
The tools of that time no longer exist in that form. Today, the URL Inspection tool in Search Console shows the canonical URL Google has selected, next to the canonical you declared. The index coverage report is now called “Page indexing”. We have not re-tested how it handles canonicals from the rendered HTML today. According to Vercel (December 2024), AI crawlers such as GPTBot and ClaudeBot do not execute JavaScript and do not see such a canonical at all. The basics are covered in the canonical tag guide.
How to check your canonicals
- Set the canonical in the source code, with an absolute URL and only once in the head.
- Check whether a script, a plugin or a tag in Tag Manager adds a second canonical or changes the existing one.
- Compare the source code and the rendered HTML. The following script shows both values.
- Use URL Inspection to check which URL Google has selected as canonical.
Common mistakes
- The source code contains a self-referencing canonical, and JavaScript changes it to a different URL.
- A tag in Tag Manager adds a canonical, and the old one stays in place.
- A script closes the head too early. The canonical then ends up in the body and does not count.
- A result is judged after a few days, even though Google needs longer to render.
FAQ
Does Google respect a canonical set via JavaScript?
Yes. In our 2018 test, Google canonicalized all four test pages according to the inserted canonical. Today, Google's documentation confirms that Search picks up an inserted canonical during rendering.
May JavaScript change an existing canonical?
Google advises against it. The canonical set via JavaScript should name the same URL as the one in the source code. If there is none in the source code, JavaScript may set it.
Can I set canonicals with Google Tag Manager?
Technically yes, as the test shows. It is not much use as a permanent solution, because the tag only takes effect after rendering and AI crawlers without rendering do not see it.
How long does it take for Google to pick up a JavaScript canonical?
In our test, 10 to 34 days. This is a measurement from 2018 on less important pages.
Where can I see which canonical Google has chosen?
In the URL Inspection tool in Search Console, under “Google-selected canonical”.
Sources
Retrieved on October 15, 2026. If something is out of date or missing, let us know.
- Google, Understand the JavaScript SEO basics: https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics · As of Mar 4, 2026
- Google, How to specify a canonical URL: https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls · As of Jul 10, 2026
- Search Console Help, URL Inspection tool: https://support.google.com/webmasters/answer/9012289 · Retrieved Oct 15, 2026
- Search Console Help, Page indexing report: https://support.google.com/webmasters/answer/7440203 · Retrieved Oct 15, 2026
- Vercel, The rise of the AI crawler: https://vercel.com/blog/the-rise-of-the-ai-crawler · Dec 17, 2024