-
-
Save arafathusayn/101a211b3d8122876d70cf1af04ae81d to your computer and use it in GitHub Desktop.
| /** | |
| * Remove Tawk.to Branding | |
| * | |
| * What it hides: | |
| * - Footer branding links (tawk.to, utm_source=tawk-messenger) | |
| * - "Add Chat to your website" link | |
| * - Popout button/icon | |
| * - Branding container classes | |
| * | |
| * Key design decisions: | |
| * - CSS injection over DOM removal (less disruptive, survives re-renders) | |
| * - MutationObserver over setInterval (reacts to changes, no wasted cycles) | |
| * - Debounced re-scans (Tawk rebuilds its widget DOM sometimes) | |
| * - iframe `load` listener stays active (catches SPA navigations) | |
| * - JS fallback for popout buttons (`:has()` unsupported in older browsers) | |
| */ | |
| ;(function removeTawkBranding() { | |
| "use strict"; | |
| // ββ Config ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| var STYLE_ID = "hide-tawk-branding"; | |
| // NOTE: No `:contains()` (jQuery-only, invalid in browsers). | |
| // No `:has()` in CSS (Firefox < 121, older Safari/Chrome). | |
| // Popout buttons handled via JS fallback below. | |
| var BRANDING_CSS = [ | |
| "a[href*='tawk.to'] { display: none !important; }", | |
| "a[href*='utm_source=tawk-messenger'] { display: none !important; }", | |
| "a[title*='Add Chat to your website'] { display: none !important; }", | |
| ".tawk-branding { display: none !important; }", | |
| "[class*='tawk-branding'] { display: none !important; }", | |
| ".tawk-padding-small { display: none !important; }", | |
| ".tawk-icon-popout { display: none !important; }", | |
| ].join("\n"); | |
| var RETRY_DELAY_MS = 1500; | |
| // ββ State βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| var processedIframes = new WeakSet(); | |
| var pendingRetries = new Map(); | |
| var debounceTimer = null; | |
| // ββ Core ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| /** | |
| * Inject a <style> into a document. Returns true on success. | |
| */ | |
| function injectStyle(doc) { | |
| try { | |
| if (!doc || !doc.createElement) return false; | |
| if (doc.getElementById(STYLE_ID)) return true; | |
| var style = doc.createElement("style"); | |
| style.id = STYLE_ID; | |
| style.textContent = BRANDING_CSS; | |
| var target = doc.head || doc.documentElement; | |
| if (target) { | |
| target.appendChild(style); | |
| return true; | |
| } | |
| } catch (_) { | |
| // Cross-origin β expected. | |
| } | |
| return false; | |
| } | |
| /** | |
| * JS fallback: hide popout buttons for browsers without CSS `:has()`. | |
| */ | |
| function hidePopoutButtons(doc) { | |
| try { | |
| if (!doc || !doc.querySelectorAll) return; | |
| var icons = doc.querySelectorAll(".tawk-icon-popout"); | |
| for (var i = 0; i < icons.length; i++) { | |
| var btn = icons[i].closest("button"); | |
| if (btn) btn.style.setProperty("display", "none", "important"); | |
| } | |
| } catch (_) {} | |
| } | |
| /** | |
| * Inject styles into an iframe. Retries once if contentDocument isn't ready. | |
| */ | |
| function injectIntoIframe(iframe) { | |
| try { | |
| var doc = iframe.contentDocument; | |
| if (!doc) { | |
| // Schedule a single retry if iframe not ready yet | |
| if (!pendingRetries.has(iframe)) { | |
| var timeout = setTimeout(function () { | |
| pendingRetries.delete(iframe); | |
| injectIntoIframe(iframe); | |
| }, RETRY_DELAY_MS); | |
| pendingRetries.set(iframe, timeout); | |
| } | |
| return; | |
| } | |
| injectStyle(doc); | |
| hidePopoutButtons(doc); | |
| } catch (_) { | |
| // Cross-origin β expected. | |
| } | |
| } | |
| /** | |
| * Process a chat iframe: mark as processed, inject now, re-inject on reload. | |
| */ | |
| function handleIframe(iframe) { | |
| if (processedIframes.has(iframe)) return; | |
| var title = (iframe.title || "").toLowerCase(); | |
| if (title.indexOf("chat") === -1) return; | |
| processedIframes.add(iframe); | |
| // Inject immediately (may already be loaded) | |
| injectIntoIframe(iframe); | |
| // Re-inject on subsequent loads (SPA navigation, widget rebuild). | |
| // Intentionally NOT `{ once: true }` β Tawk can reload iframe content. | |
| iframe.addEventListener("load", function () { | |
| injectIntoIframe(iframe); | |
| }); | |
| } | |
| /** | |
| * Scan a root document for all chat iframes. | |
| */ | |
| function scanIframes(root) { | |
| try { | |
| var iframes = (root || document).querySelectorAll("iframe"); | |
| for (var i = 0; i < iframes.length; i++) { | |
| handleIframe(iframes[i]); | |
| } | |
| } catch (_) {} | |
| } | |
| // ββ Observer ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function onMutations(mutations) { | |
| var foundNewIframe = false; | |
| for (var i = 0; i < mutations.length; i++) { | |
| var added = mutations[i].addedNodes; | |
| for (var j = 0; j < added.length; j++) { | |
| var node = added[j]; | |
| if (node.nodeName === "IFRAME") { | |
| handleIframe(node); | |
| foundNewIframe = true; | |
| } else if (node.nodeType === 1 && node.querySelectorAll) { | |
| var nested = node.querySelectorAll("iframe"); | |
| if (nested.length) { | |
| for (var k = 0; k < nested.length; k++) { | |
| handleIframe(nested[k]); | |
| } | |
| foundNewIframe = true; | |
| } | |
| } | |
| } | |
| } | |
| // Debounced re-scan: Tawk sometimes rebuilds its widget DOM entirely, | |
| // so existing iframes may get new content without a new IFRAME node. | |
| if (foundNewIframe && !debounceTimer) { | |
| debounceTimer = setTimeout(function () { | |
| debounceTimer = null; | |
| scanIframes(); | |
| hidePopoutButtons(document); | |
| }, 500); | |
| } | |
| } | |
| // ββ Bootstrap βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| function start() { | |
| // Main document branding (outside iframes) | |
| injectStyle(document); | |
| hidePopoutButtons(document); | |
| // Initial iframe scan | |
| scanIframes(); | |
| // Watch for dynamically added iframes | |
| if (typeof MutationObserver !== "undefined" && document.body) { | |
| var observer = new MutationObserver(onMutations); | |
| observer.observe(document.body, { childList: true, subtree: true }); | |
| // Cleanup | |
| window.addEventListener("beforeunload", function () { | |
| observer.disconnect(); | |
| pendingRetries.forEach(clearTimeout); | |
| pendingRetries.clear(); | |
| if (debounceTimer) { | |
| clearTimeout(debounceTimer); | |
| debounceTimer = null; | |
| } | |
| }); | |
| } | |
| } | |
| // Guard: script may be in <head> before document.body exists | |
| if (document.body) { | |
| start(); | |
| } else { | |
| document.addEventListener("DOMContentLoaded", start); | |
| } | |
| })(); |
Please provide new tawk-chat brand removing code because previous code not working..
Below mentioned script not working currently.
<script> var removeBranding = function() { try { const style = document.createElement('style'); style.textContent = '.tawk-padding-small {display:none !important;}'; document.querySelector('iframe[title*="chat"]:nth-child(2)').contentDocument.head.appendChild(style) } catch (e) {} } var tick = 100 setInterval(removeBranding, tick) </script>@arafathusayn any updates on a new version βοΈ? Seems like the current one no longer works
@hazelcorp2011-cmd π§ try this β it seems the Tawk guys were smart π they removed the href, so you canβt easily target it anymore with:
a[href*="tawk.to"]But haha πππππ you can still catch that anchor using other CSS attribute selectors. See below π
method one just hiding the brand
// ================== embed tawk.to script ==================
useEffect(() => {
const BRANDING_SELECTORS = `
/* expanded widget branding */
a[style*="font-size: 12px"][style*="font-weight: 400"][style*="padding: 0.5em"],
/* minimized widget branding */
a[style*="font-size: 12px"][style*="border-radius: 100px"]
`;
const injectStyle = (doc: Document) => {
if (doc.getElementById("hide-tawk-branding")) return;
const style = doc.createElement("style");
style.id = "hide-tawk-branding";
style.textContent = `
${BRANDING_SELECTORS} {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
width: 0 !important;
height: 0 !important;
overflow: hidden !important;
max-width: 0 !important;
max-height: 0 !important;
}
`;
(doc.head || doc.documentElement).prepend(style);
};
const handleIframe = (iframe: HTMLIFrameElement) => {
const apply = () => {
try {
const doc =
iframe.contentDocument ||
iframe.contentWindow?.document;
if (!doc) return;
injectStyle(doc);
} catch {
// cross-origin iframe β expected for non-tawk iframes
}
};
apply();
iframe.addEventListener("load", apply);
};
// existing iframes
document.querySelectorAll("iframe").forEach((iframe) => {
handleIframe(iframe as HTMLIFrameElement);
});
// future iframes
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLIFrameElement) {
handleIframe(node);
}
if (node instanceof HTMLElement) {
node.querySelectorAll("iframe").forEach((iframe) => {
handleIframe(iframe as HTMLIFrameElement);
});
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
return () => {
observer.disconnect();
};
}, []);
method two hiding the brand and adding ur own brand
// ================== embed tawk.to script ==================
useEffect(() => {
if (typeof window === "undefined") return;
const s1 = document.createElement("script");
const s0 = document.getElementsByTagName("script")[0];
s1.async = true;
s1.src = "Add link to the widget";
s1.charset = "UTF-8";
s1.setAttribute("crossorigin", "*");
s0?.parentNode?.insertBefore(s1, s0);
}, []);
// //================ latest hide branding and add ur custom branding =================
useEffect(() => {
const BRAND_TEXT = "Powered by bloodykheeng";
const OVERLAY_ID = "custom-tawk-branding";
// =========================
// create stable branding overlay
// =========================
let branding = document.getElementById(OVERLAY_ID);
if (!branding) {
branding = document.createElement("div");
branding.id = OVERLAY_ID;
branding.innerText = BRAND_TEXT;
Object.assign(branding.style, {
position: "fixed",
bottom: "30px",
right: "100px",
zIndex: "999999",
background: "#fff",
padding: "6px 12px",
borderRadius: "999px",
fontSize: "11px",
color: "#6b7280",
boxShadow: "0 4px 14px rgba(0,0,0,0.12)",
pointerEvents: "none",
transition: "opacity .2s ease",
opacity: "0",
visibility: "hidden",
});
document.body.appendChild(branding);
}
// =========================
// show/hide overlay
// =========================
const showBranding = () => {
if (!branding) return;
branding.style.opacity = "1";
branding.style.visibility = "visible";
};
const hideBranding = () => {
if (!branding) return;
branding.style.opacity = "0";
branding.style.visibility = "hidden";
};
// =========================
// tawk callbacks
// =========================
const w = window as any;
w.Tawk_API = w.Tawk_API || {};
w.Tawk_API.onChatMaximized = showBranding;
w.Tawk_API.onChatStarted = showBranding;
w.Tawk_API.onChatMinimized = hideBranding;
w.Tawk_API.onChatHidden = hideBranding;
// =========================
// aggressively hide real branding
// =========================
const injectStyle = (doc: Document) => {
if (doc.getElementById("hide-real-tawk-branding")) return;
const style = doc.createElement("style");
style.id = "hide-real-tawk-branding";
style.textContent = `
a[style*="font-size: 12px"][style*="padding: 0.5em"],
a[style*="border-radius: 100px"] {
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
transform: scale(0) !important;
}
`;
(doc.head || doc.documentElement).prepend(style);
};
const handleIframe = (iframe: HTMLIFrameElement) => {
const apply = () => {
try {
const doc =
iframe.contentDocument ||
iframe.contentWindow?.document;
if (!doc) return;
injectStyle(doc);
} catch {
// cross-origin
}
};
apply();
iframe.addEventListener("load", apply);
};
// existing iframes
document.querySelectorAll("iframe").forEach((iframe) => {
handleIframe(iframe as HTMLIFrameElement);
});
// future iframes
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLIFrameElement) {
handleIframe(node);
}
if (node instanceof HTMLElement) {
node.querySelectorAll("iframe").forEach((iframe) => {
handleIframe(iframe as HTMLIFrameElement);
});
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
return () => {
observer.disconnect();
branding?.remove();
};
}, []);
@hazelcorp2011-cmd π§ try this β it seems the Tawk guys were smart π they removed the
href, so you canβt easily target it anymore with:a[href*="tawk.to"]But haha πππππ you can still catch that anchor using other CSS attribute selectors. See below π
method one just hiding the brand
// ================== embed tawk.to script ================== useEffect(() => { const BRANDING_SELECTORS = ` /* expanded widget branding */ a[style*="font-size: 12px"][style*="font-weight: 400"][style*="padding: 0.5em"], /* minimized widget branding */ a[style*="font-size: 12px"][style*="border-radius: 100px"] `; const injectStyle = (doc: Document) => { if (doc.getElementById("hide-tawk-branding")) return; const style = doc.createElement("style"); style.id = "hide-tawk-branding"; style.textContent = ` ${BRANDING_SELECTORS} { display: none !important; visibility: hidden !important; opacity: 0 !important; pointer-events: none !important; width: 0 !important; height: 0 !important; overflow: hidden !important; max-width: 0 !important; max-height: 0 !important; } `; (doc.head || doc.documentElement).prepend(style); }; const handleIframe = (iframe: HTMLIFrameElement) => { const apply = () => { try { const doc = iframe.contentDocument || iframe.contentWindow?.document; if (!doc) return; injectStyle(doc); } catch { // cross-origin iframe β expected for non-tawk iframes } }; apply(); iframe.addEventListener("load", apply); }; // existing iframes document.querySelectorAll("iframe").forEach((iframe) => { handleIframe(iframe as HTMLIFrameElement); }); // future iframes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node instanceof HTMLIFrameElement) { handleIframe(node); } if (node instanceof HTMLElement) { node.querySelectorAll("iframe").forEach((iframe) => { handleIframe(iframe as HTMLIFrameElement); }); } }); }); }); observer.observe(document.documentElement, { childList: true, subtree: true, }); return () => { observer.disconnect(); }; }, []);method two hiding the brand and adding ur own brand
// ================== embed tawk.to script ================== useEffect(() => { if (typeof window === "undefined") return; const s1 = document.createElement("script"); const s0 = document.getElementsByTagName("script")[0]; s1.async = true; s1.src = "Add link to the widget"; s1.charset = "UTF-8"; s1.setAttribute("crossorigin", "*"); s0?.parentNode?.insertBefore(s1, s0); }, []); // //================ latest hide branding and add ur custom branding ================= useEffect(() => { const BRAND_TEXT = "Powered by bloodykheeng"; const OVERLAY_ID = "custom-tawk-branding"; // ========================= // create stable branding overlay // ========================= let branding = document.getElementById(OVERLAY_ID); if (!branding) { branding = document.createElement("div"); branding.id = OVERLAY_ID; branding.innerText = BRAND_TEXT; Object.assign(branding.style, { position: "fixed", bottom: "30px", right: "100px", zIndex: "999999", background: "#fff", padding: "6px 12px", borderRadius: "999px", fontSize: "11px", color: "#6b7280", boxShadow: "0 4px 14px rgba(0,0,0,0.12)", pointerEvents: "none", transition: "opacity .2s ease", opacity: "0", visibility: "hidden", }); document.body.appendChild(branding); } // ========================= // show/hide overlay // ========================= const showBranding = () => { if (!branding) return; branding.style.opacity = "1"; branding.style.visibility = "visible"; }; const hideBranding = () => { if (!branding) return; branding.style.opacity = "0"; branding.style.visibility = "hidden"; }; // ========================= // tawk callbacks // ========================= const w = window as any; w.Tawk_API = w.Tawk_API || {}; w.Tawk_API.onChatMaximized = showBranding; w.Tawk_API.onChatStarted = showBranding; w.Tawk_API.onChatMinimized = hideBranding; w.Tawk_API.onChatHidden = hideBranding; // ========================= // aggressively hide real branding // ========================= const injectStyle = (doc: Document) => { if (doc.getElementById("hide-real-tawk-branding")) return; const style = doc.createElement("style"); style.id = "hide-real-tawk-branding"; style.textContent = ` a[style*="font-size: 12px"][style*="padding: 0.5em"], a[style*="border-radius: 100px"] { opacity: 0 !important; visibility: hidden !important; pointer-events: none !important; transform: scale(0) !important; } `; (doc.head || doc.documentElement).prepend(style); }; const handleIframe = (iframe: HTMLIFrameElement) => { const apply = () => { try { const doc = iframe.contentDocument || iframe.contentWindow?.document; if (!doc) return; injectStyle(doc); } catch { // cross-origin } }; apply(); iframe.addEventListener("load", apply); }; // existing iframes document.querySelectorAll("iframe").forEach((iframe) => { handleIframe(iframe as HTMLIFrameElement); }); // future iframes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node instanceof HTMLIFrameElement) { handleIframe(node); } if (node instanceof HTMLElement) { node.querySelectorAll("iframe").forEach((iframe) => { handleIframe(iframe as HTMLIFrameElement); }); } }); }); }); observer.observe(document.documentElement, { childList: true, subtree: true, }); return () => { observer.disconnect(); branding?.remove(); }; }, []);
I was try, but still not remove tawk branding
Anyone can help me for removing tawk chat branding with plan JS Code.
Removed branding and also 2 items from dropdown menu.
Tested on tawk.to plugin for wordpress.
Works on mobile also.
Here:
var removeBranding = function () {
var iframes = document.querySelectorAll("iframe");
iframes.forEach(function (ifr, idx) {
try {
var doc = ifr.contentDocument || (ifr.contentWindow && ifr.contentWindow.document);
if (!doc) return;
var btn = doc.querySelector('a[class*="tawk-button-small"]');
if (btn) {
btn.remove();
}
var popoutIcon = doc.querySelector("i.tawk-icon.tawk-icon-popout");
if (popoutIcon) {
var popoutButton = popoutIcon.closest("button");
if (popoutButton) {
popoutButton.remove();
}
}
var byHref = doc.querySelector('a[href*="tawk.to/?utm_source=tawk-messenger"], a[href*="tawk.to/?utm_"]');
if (byHref) {
console.log("Removed by href:", byHref);
byHref.remove();
return;
}
var svgBranding = doc.querySelector('a svg[viewBox="0 0 107 15"]');
if (svgBranding) {
var brandingLink = svgBranding.closest("a");
if (brandingLink) {
console.log("Removed SVG branding:", brandingLink);
brandingLink.remove();
return;
}
}
var nodes = Array.from(doc.querySelectorAll("a, div, span"));
var poweredBy = nodes.find(function (el) {
return normalizeText(el.textContent).includes("powered by tawk.to");
});
if (poweredBy) {
console.log("Removed powered by text:", poweredBy);
var a = poweredBy.tagName === "A" ? poweredBy : poweredBy.querySelector("a");
(a || poweredBy).remove();
}
}
catch (e) {
}
});
};
setInterval(removeBranding, 250);
Have u made ur own app @hoangbits