My Account

First Time Here?

Create an Account

Create an account to manage your giving, track your impact, and be part of the solution.

Welcome Back!

Log In

Good to see you again! Log in to manage your giving and see the impact you're making.

Enter the email address you used to give or communicate with us.

/** * H4KI — Givecloud exit-intent popup suppressor * * Hides the "Are you sure you want to leave without making a difference?" * modal that Givecloud's Giving Experience widget shows on exit intent. * * Detection is text-based (not class-based) because the widget is React + * Tailwind and its utility classes can change between Givecloud releases. * * Works whether it's loaded: * - inside a Givecloud-hosted page / the widget document itself * (Givecloud admin custom script section), or * - on the parent WordPress page (the embedded widget lives in a * same-origin iframe, so page JS can reach into it). * * Last verified against widget markup: Jul 2026. */ (function () { 'use strict'; // The phrase that identifies the exit-intent modal. var TRIGGER = /leave without making a difference/i; function dismiss(container, doc) { var target = deepestMatch(container); var overlay = fixedAncestor(target, doc) || container; if (overlay.__gcExitHidden) return; overlay.__gcExitHidden = true; // Hide immediately so the donor never sees a flash of the modal. overlay.style.setProperty('display', 'none', 'important'); // Then let the widget close itself via its own "Close" control so React // state, backdrop, and body scroll-lock are cleaned up properly. var controls = overlay.querySelectorAll('button, a, [role="button"]'); for (var i = 0; i < controls.length; i++) { if (/^\s*close\b/i.test(controls[i].textContent || '')) { try { controls[i].click(); } catch (e) { /* ignore */ } break; } } // Safety net: if the widget reuses this same DOM node for a *different* // modal later (e.g. a payment sheet), un-hide it so we never block a // legitimate dialog. var restore = setInterval(function () { if (!overlay.isConnected) { clearInterval(restore); return; } if (!TRIGGER.test(overlay.textContent || '')) { overlay.style.removeProperty('display'); overlay.__gcExitHidden = false; clearInterval(restore); } }, 500); } // Walk down to the innermost element still containing the trigger text. function deepestMatch(root) { var el = root, descend = true; while (descend) { descend = false; var kids = el.children || []; for (var i = 0; i < kids.length; i++) { if (TRIGGER.test(kids[i].textContent || '')) { el = kids[i]; descend = true; break; } } } return el; } // Climb back up to the position:fixed overlay that wraps the whole modal // (card + gray backdrop), so hiding it removes everything at once. function fixedAncestor(el, doc) { var win = doc.defaultView || window; while (el && el !== doc.body) { if (win.getComputedStyle(el).position === 'fixed') return el; el = el.parentElement; } return null; } function sweep(doc) { if (!doc.body || !TRIGGER.test(doc.body.textContent || '')) return; var kids = doc.body.children; for (var i = 0; i < kids.length; i++) { if (TRIGGER.test(kids[i].textContent || '')) dismiss(kids[i], doc); } } function watch(doc) { if (!doc || !doc.body || doc.__gcExitWatcher) return; doc.__gcExitWatcher = true; new MutationObserver(function () { sweep(doc); }) .observe(doc.body, { childList: true, subtree: true }); sweep(doc); // in case the modal is already showing } // Watch the document this script runs in… watch(document); // …and keep checking for same-origin iframes (the embedded widget on the // WordPress site). Re-runs every second because Givecloud creates — and can // rewrite — the widget iframe after page load, which discards observers. setInterval(function () { watch(document); var frames = document.querySelectorAll('iframe'); for (var i = 0; i < frames.length; i++) { try { watch(frames[i].contentDocument); } catch (e) { /* cross-origin */ } } }, 1000); })();