OK, I think the issue is that when you decode the gmnotes, you get the HTML formatting, too. So something like: <p>-M1234567890abcdef</p> ...will never match: -M1234567890abcdef There are a few ways to get around that... the simplest would probably be just testing for the presence of those <p> tags. Change this line: if(doorid === doorobjid) { ...to be... if(`<p>${doorid}</p>` === doorobjid) { That should do it. "...but if you leave the camera rolling..." That will work if all you are doing is storing that one piece of data in the gmnotes field. There might come a time where you'll want to use another script that requires other information to be in the gmnotes field, too, so I'd suggest going for a slightly different option that gives you a little more flexibility. Let's imagine that any information could be in the gmnotes, but if the dooricon's ID shows up on a line all by itself, that's what we're looking for. Testing any single line can use a regex like this: /<p>\s*([a-zA-Z0-9-_]+)<\/p>/ That will put the "thing that might be the ID" within the group 1 returns. So you could do a matchAll against the regex and then test if any of the group 1 returns match our id. That would look more like this: on('change:door', function (obj) { let doorobjid = obj.id //doorobjid is the object id of the door that was changed, so opened or closed let doors = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", layer: "objects", name: "dooricon" }); let idrx = /<p>\s*([a-zA-Z0-9-_]+)\s*<\/p>/gm; //finds all tokens on the object layer named dooricon, all of which are multi-sided tokens doors.forEach(d => { let gmNotes = decondURIComponent(d.get("gmnotes")); if (gmNotes.matchAll(idrx).some(v => v[1] === doorobjid)) { let dooriconid = d.id; var doorobj = getObj('door', doorobjid) //this is done to test if the actual door is open or closed sendChat('test', 'door id is same') //in all of my testing, I have never gotten the above message to trigger, so somehow they are not considered equivalent...even though when I check their values they appear the same if (doorobj.isOpen) { sendChat('test', 'door is open') sendChat('system', '!token-mod --ids ' + dooriconid + ' --set currentside|1'); } else { sendChat('test', 'door is closed') sendChat('system', '!token-mod --ids ' + dooriconid + ' --set currentside|2'); }; } }); }); Note that I changed the underscore "_.each" function to be the native ".forEach()" function, and also that you'd duplicated/overwritten your "obj" variable within this function. You used the same name for the object being passed into the callback of the "on(change:door)" at the top, do I changed the later iteration through the array of doors to be just "d". (Above code is untested, btw). "...but if you leave the camera rolling..." For a simple change (like the visible side of a token), you can make the change to the dooricon yourself, without having to use TokenMod, if you want. I'll leave it to you to put together, but it would just be using the .set() function on the "d" object. That's discussed at the top of this page .