aka: the #titlegeddon bookmarklet
Google has stirred up some dust all around the SEO world with their rewriting of websites‘ titles.
SEO folks are now trying to figure out how Google is rewriting their titles.
Fede Gómez, a WordPress developer from Toledo, Spain has come up with a nice JavaScript bookmarklet to be used on Google’s SERP pages. It checks for the actual website’s title tag and compares it to the one shown by Google.
It does a great job at what it is supposed to do. Go and check it out.
My version of the bookmarklet

For my use, I have altered it a bit and added some code. I wanted to not only see the current title tag of the websites, but also the (first) <h1> and see whether Google may have used the <h1> heading instead of the title tag.
- Checks if the title tag shown in Google SERPs is the same as the title tag used on the respective page
- Highlights red if the title is different, showing the title used on the respective page
- Highlights green if the title is the same as on the page
- Highlights whether Google has truncated the title (currently only when „…“ is in Google’s title – still working on that)
- Highlights if the title shown by Google in the SERPs is actually the page’s h1 heading
- Shows if no h1 heading was found on the page
- Downloads a JSON file if you want
This data will be created when all Ajax requests have completed and the data has been gathered.
The file download will start automatically when you click the button and ask you where to save the file.
The filename will be comparison-{your google query}.json.
See below image for a preview of what this will look like.

Use my version of the bookmarklet
So, if you like, you can use my bookmarklet. Just drag the following button into your bookmarks toolbar and use it on Google’s search results pages.
Stay up to date and get updates on this bookmarklet (and more)
To stay updated on this bookmarklet and get notified once a new version comes out, please sign up to my little free newsletter.
Or copy/ paste the following code into a new bookmark’s URL field
javascript:(function()%7Bjavascript%3A (function (doc) %7Bvar changed %3D 0%3Bfunction checkTitles() %7Bconsole.log('jQuery version '%2C %24.fn.jquery%2C ' loaded')%3Bif(%24('%23chtop').length) %7B%24('%23chtop').remove()%3B%7D%24('%23result-stats').append('<div id%3D"chtop" style%3D"display%3A inline-block"><%2Fdiv>')%3B%24('%23chtop').append('<div style%3D"display%3A inline-block%3B color%3A red%3B" id%3D"waitforme">Please wait...<%2Fdiv>')%3Bvar position %3D 1%3Bvar items %3D %5B%5D%3Bvar results %3D %24('%23rso .g').not('.kno-kp .g').find('a%3Afirst')%3B%24('.title-changed%2C %23CountTitlesChanged').remove()%3Bconsole.log(results)%3Bresults.each(function () %7Bif (!%24(this).parents('.related-question-pair').length) %7Bvar parent %3D %24(this).closest('.tF2Cxc').length > 0 %3F %24(this).closest('.tF2Cxc') %3A %24(this).closest('li')%3Bitems.push(%5Bposition%2C %24(this).find('h3').text()%2C encodeURI(%24(this).attr('href'))%2C parent%5D)%3Bposition%2B%2B%3B%7D%7D)%3Bconst allItems %3D %5B%5D%3Bvar numItems %3D 1%3Bcors_proxies %3D %5B'https%3A%2F%2Fapi.codetabs.com%2Fv1%2Fproxy%3Fquest%3D'%2C 'https%3A%2F%2Fcors.bridged.cc%2F'%5D%3Bitems.forEach(item %3D> %7Bvar useItem %3D %7B%7D%3Bvar use_url %3D item%5B2%5D%3BuseItem.url %3D use_url%3B%24.ajax(%7Burl%3A cors_proxies%5BMath.floor(Math.random() * cors_proxies.length)%5D %2B item%5B2%5D%2Csuccess%3A function (data%2C status%2C xhr) %7Btitle %3D %24(data).filter('title').text().trim()%3Bvar h1 %3D %24(data).find("h1%3Afirst").text().trim()%3BuseItem.pageTitle %3D title%3BuseItem.googleTitle %3D item%5B1%5D%3BuseItem.pageH1 %3D h1%3BuseItem.uses_title %3D false%3BuseItem.uses_h1 %3D false%3BuseItem.title_rewritten %3D false%3BuseItem.title_truncated %3D false%3Bvar html %3D '<div class%3D"title-changed">'%3Bvar uses_h1 %3D false%3Bif (h1 %3D%3D item%5B1%5D %26%26 h1 !%3D useItem.pageTitle) %7Buses_h1 %3D true%3B%7Dif(useItem.googleTitle.includes("...")) %7Bvar google_title_split %3D useItem.googleTitle.split("...")%5B0%5D%3Bvar compare_google_title_truncated %3D google_title_split.replace("..."%2C "")%3Bif((useItem.pageTitle.includes(compare_google_title_truncated))) %7BuseItem.title_truncated %3D true%3B%7D%7Dif (title !%3D item%5B1%5D) %7Bvar display_title_pre %3D "Title%3A "%3Bvar display_title_color %3D "%23ff6961"%3Bif(useItem.title_truncated) %7Bdisplay_title_pre %3D "Title TRUNCATED%3A "%3Bdisplay_title_color %3D "%23a6cc1d"%3B%7Dhtml %2B%3D '<span style%3D"font-weight%3A bold%3Bcolor%3A %23ff6961%3B">'%2B display_title_pre %2B ' ' %2B title %2B '<%2Fspan>'%3Bchanged%2B%2B%3BuseItem.title_rewritten %3D true%3B%7D else %7Bhtml %2B%3D '<span style%3D"font-weight%3A bold%3Bcolor%3A darkgreen%3B">Title%3A ' %2B item%5B1%5D %2B '<%2Fspan>'%3B%7Dhtml %2B%3D '<div style%3D"display%3A block%3B padding%3A2px 0%3B font-weight%3Abold%3B color%3A dodgerblue">'%3Bif (h1.length %26%26 typeof h1 %3D%3D%3D "string") %7Bhtml %2B%3D 'h1%3A ' %2B h1%3B%7D else %7Bhtml %2B%3D 'No h1 found on page'%3B%7Dhtml %2B%3D '<%2Fdiv>'%3Bif (uses_h1) %7BuseItem.uses_h1 %3D true%3Bhtml %2B%3D '<div style%3D"display%3A inline-block%3B background-color%3A %23ffd811%3B border%3A 1px solid rgb(74%2C 85%2C 104)%3B color%3A rgb(74%2C 85%2C 104)%3B padding-left%3A 4px%3B padding-right%3A 4px%3B border-radius%3A 4px%3B"><b>Uses H1<%2Fb><%2Fdiv>'%3B%7Dhtml %2B%3D '<%2Fdiv>'%3Bitem%5B3%5D.find('div').first().append(html)%3BallItems.push(useItem)%3B%7D%2Cerror%3A function (xhr%2C status%2C error) %7Bvar html %3D '<div class%3D"title-changed">'%3Bhtml %2B%3D '<span style%3D"font-weight%3A bold%3Bcolor%3A lightslategray%3B">Error%3A Request could not be processed<%2Fspan>'%3Bhtml %2B%3D '<%2Fdiv>'%3Bitem%5B3%5D.find('div').first().append(html)%3B%7D%2Ccomplete%3A function (xhr%2C status) %7Bif (numItems %3D%3D items.length) %7BpetitionCompleted(allItems)%3B%7D else %7BnumItems%2B%2B%3B%7D%7D%7D)%3B%7D)%3B%24(document).on('click'%2C '%23downloadJsonData'%2C function () %7BdownloadObjectAsJson(allItems%2C "comparison-" %2B %24("input%5Bname%3Dq%5D").val())%3B%7D)%7Dfunction petitionCompleted(allItems) %7B%24('%23result-stats').append('<span id%3D"CountTitlesChanged"> - ' %2B changed %2B ' titles have changed<%2Fspan>')%3B%24('%23chtop').append('<span id%3D"downloadJsonData" style%3D"cursor%3Apointer%3B background-color%3A %23fff%3B border%3A1px solid %23000%3B border-radius%3A3px%3B padding%3A2px 5px%3B margin-left%3A 10px">Download JSON<%2Fspan>')%3Bdocument.getElementById('waitforme').style.display %3D "none"%3B%7Dfunction downloadObjectAsJson(exportObj%2C exportName) %7Bvar dataStr %3D "data%3Atext%2Fjson%3Bcharset%3Dutf-8%2C" %2B encodeURIComponent(JSON.stringify(exportObj))%3Bvar downloadAnchorNode %3D document.createElement('a')%3BdownloadAnchorNode.setAttribute("href"%2C dataStr)%3BdownloadAnchorNode.setAttribute("download"%2C exportName %2B ".json")%3Bdocument.body.appendChild(downloadAnchorNode)%3BdownloadAnchorNode.click()%3BdownloadAnchorNode.remove()%3B%7Dif (typeof jQuery %3D%3D 'undefined') %7Bvar script_jQuery %3D document.createElement('script')%3Bscript_jQuery.src %3D 'https%3A%2F%2Fcode.jquery.com%2Fjquery-latest.min.js'%3Bscript_jQuery.onload %3D checkTitles%3Bdoc.body.appendChild(script_jQuery)%3B%7D else %7BcheckTitles()%3B%7D%7D)(document)%7D)()
Release History of my version:
- 2021-09-07:
Bugfix: Bookmarklet showed „uses h1“ when title tag and h1 were similar. -> Fixed.
Improvement: Now checks whether Google simply truncated the original page’s title - 2021-09-05: Now without automatic export. Adds a „download JSON“ button at the top.
- 2021-09-03: Now we have got (automatic, sorry) JSON-Export
- 2021-09-03: First release.
If you’d like to add something: here’s the repo on github.
Oh, and here’s a list of other useful SEO bookmarklets :)
Thanks Christian! I’ll translate it into french.
Could you give the code for the version without JSON export?
Hi Olivier. Thank you!
You can find the source code on GitHub. There is a link at the end of the article.
You can simply remove the function call on line 83. That way the download won’t be triggered.
I’ve used the minified code… I’m not able to remove the function call (and the definition of the function)
Hi Olivier. I have updated the bookmarklet so you have to click a button to download the data :)
Christian, thank you so much! I like how I am able to quickly access all data with just one click. Keep sharing such great things with us. Once again, thank you.
Hello Ashok. Thank you very much for your kind words. I am glad this is helpful to you.
Hi Christian,
Well great information. This information will definitely give some boost to increase my ranks in search engines. Thanks for sharing.
Thank you very much :) I’m glad it’s useful to you.
Thanks! I’ve translated it in french, provided it on my article https://www.webrankinfo.com/dossiers/conseils/titre-serp and in my list of bookmaklets https://www.webrankinfo.com/dossiers/outils/bookmarklets
Thanks Olivier. I just read the article. If you use the updated code from github, it won’t auto-download the JSON, but put a button at the top of the SERPs which lets you download the JSON data.
Thank you for sharing this, it’s really helpful! I’ve had a H2 show up as the title for one of my websites. Are other people seeing this as well do you know?
Thanks for sharing this JS Bookmarklet Christian Hänsel,
Really it’s a time saver for us to know from where is title take taken …
Thank for sharing this for us. It is also available for Meta Description?
Thanks for good seo resource
A very good gadget for a quick check. More like this! Thank you
The bookmarklet is not working properly as of Feb 2022. Can you please take a look at it?
Hey Lucas. Thank you very much for your message. It should be working now.
It is very useful information, thanks for the contribution
It seems that the API from https://cors.bridged.cc has some kind of limitation that is preventing your app from accessing all the sites in the SERPs. Is there a way to bypass the limitation?
Thanks