In Javascript, is there a technique to listen for changes to the title element?
6 Answers
5 years later we finally have a better solution. Use MutationObserver!
In short:
new MutationObserver(function(mutations) {
console.log(mutations[0].target.nodeValue);
}).observe(
document.querySelector('title'),
{ subtree: true, characterData: true, childList: true }
);
With comments:
// select the target node
var target = document.querySelector('title');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
// We need only first event and only new value of the title
console.log(mutations[0].target.nodeValue);
});
// configuration of the observer:
var config = { subtree: true, characterData: true, childList: true };
// pass in the target node, as well as the observer options
observer.observe(target, config);

- 2,842
- 2
- 16
- 23

- 19,264
- 8
- 60
- 114
-
2Looks awesome, but it doesn't work when I set document.title directly: `document.title = 'test';` – wensveen Feb 12 '16 at 10:42
-
2As a workaround, you can add: `document.__defineSetter__('title', function(val) { document.querySelector('title').childNodes[0].nodeValue = val; });`. Which probably doesn't work in all browsers, unfortunately. – wensveen Feb 12 '16 at 10:50
-
12It wasn't working for me when I set `document.title` directly either. (I used Chrome 52.) However, adding `childList: true` to the config object fixed it. – eppsilon Aug 15 '16 at 23:27
-
3`new MutationObserver(function() {console.log(document.title);}).observe(document.querySelector('title'),{ childList: true });` it works – 井上智文 Dec 15 '18 at 09:07
2022 Update
Mutation Observers are unequivocally the way to go now (see Vladimir Starkov's answer), with no need for fallbacks to the older APIs mentioned below. Furthermore, DOMSubtreeModified should be actively avoided now.
I'm leaving the remainder of this answer here for posterity.
2010 Answer
You can do this with events in most modern browsers (notable exceptions being all versions of Opera and Firefox 2.0 and earlier). In IE you can use the propertychange
event of document
and in recent Mozilla and WebKit browsers you can use the generic DOMSubtreeModified
event. For other browsers, you will have to fall back to polling document.title
.
Note that I haven't been able to test this in all browsers, so you should test this carefully before using it.
2015 Update
Mutation Observers are the way to go in most browsers these days. See Vladimir Starkov's answer for an example. You may well want some of the following as fallback for older browsers such as IE <= 10 and older Android browsers.
function titleModified() {
window.alert("Title modifed");
}
window.onload = function() {
var titleEl = document.getElementsByTagName("title")[0];
var docEl = document.documentElement;
if (docEl && docEl.addEventListener) {
docEl.addEventListener("DOMSubtreeModified", function(evt) {
var t = evt.target;
if (t === titleEl || (t.parentNode && t.parentNode === titleEl)) {
titleModified();
}
}, false);
} else {
document.onpropertychange = function() {
if (window.event.propertyName == "title") {
titleModified();
}
};
}
};

- 318,141
- 75
- 454
- 536
-
An OK answer but uses object inference, assuming that all browsers that support *addEventListener* also support *DOMSubtreeModified* and that any other browser supports *onpropertychange*. – RobG Mar 03 '14 at 01:00
-
@RobG: Yes, I suppose so. I've occasionally been a little lazy on that front with Stack Overflow answers for the sake of brevity. In this case, I'd argue the inferences aren't too bad: `addEventListener` and DOM mutation events are both DOM level 2, and in both branches, a lack of browser support will not throw an error or do any harm. I don't think it's possible to reliably detect whether the browser supports detection of changes to the title anyway. – Tim Down Mar 03 '14 at 17:28
-
Perhaps setup a listener, modify the title and see if a suitable event occurs, then restore the title. – RobG Mar 04 '14 at 02:00
-
-
@VladimirStarkov: Yes, Mutation Observers are definitely the way to go in modern browsers. I'd suggest feature testing for support and using some of the above as fallback for older browsers though. – Tim Down Apr 09 '15 at 16:44
-
DOMSubtreeModified is not stanrdardized, and should not be used. https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent – Jon Koops Feb 21 '22 at 09:49
-
1@JonKoops: DOMSubtreeModified was [standardized in the DOM 3 spec](https://www.w3.org/TR/DOM-Level-3-Events/#events-mutationevents) and at the time of my last major revision to this answer in 2015, it was sensible to use as a fallback in browsers that didn't support Mutation Observers, but I absolutely agree that it should not be used now. I'll update it. – Tim Down Feb 21 '22 at 16:41
There's not a built-in event. However, you could use setInterval
to accomplish this:
var oldTitle = document.title;
window.setInterval(function()
{
if (document.title !== oldTitle)
{
//title has changed - do something
}
oldTitle = document.title;
}, 100); //check every 100ms

- 6,518
- 1
- 26
- 22
-
Yeah, that's true. Unfortunately, polling is the only option in this case. Without an event, listening is impossible (unless whatever javascript changes the title also executes a callback). – ShZ Mar 23 '10 at 02:46
-
Gecko browsers support a watch feature where you can watch for and intercept property changes. In IE I think there is an onpropertychange or similar method you can use. – scunliffe Mar 23 '10 at 02:50
This's my way, in a closure and check in startup
(function () {
var lastTitle = undefined;
function checkTitle() {
if (lastTitle != document.title) {
NotifyTitleChanged(document.title); // your implement
lastTitle = document.title;
}
setTimeout(checkTitle, 100);
};
checkTitle();
})();

- 1,943
- 18
- 22
Don't forget to remove listener when not needed anymore.
Vanilla JS:
const observer = new MutationObserver((mutations) => {
console.log(mutations[0].target.text);
});
observer.observe(document.querySelector("title"), {
subtree: true,
characterData: true,
childList: true,
})
observer.disconnect() // stops looking for changes
Or if you use React which is really neat with removing listeners, I wrote this hook:
React.useEffect(() => {
const observer = new MutationObserver(mutations => {
console.log(mutations[0].target.text)
})
observer.observe(document.querySelector("title"), {
subtree: true,
characterData: true,
childList: true,
})
return () => observer.disconnect()
}, [defaultTitle, notificationTitle])

- 8,434
- 4
- 32
- 41
const observer = new MutationObserver(([{ target }]) =>
// Log change
console.log(target.text),
)
observer.observe(document.querySelector('title'), {
childList: true,
})

- 8,804
- 9
- 59
- 90