HubSpot's Cookie Banner Loads Google Fonts - And Nobody Seems to Care
You know what's ironic? A cookie consent banner that violates privacy before you even click "Accept."
That's exactly what HubSpot's cookie banner does. It loads Google Fonts, sending your visitor's IP address to Google's servers, the moment the page loads. No consent asked. No opt-in. Just a quiet little request to fonts.googleapis.com that most people never notice.
I noticed. And it took me down a rabbit hole.
The Problem # Anchor link
If you're using HubSpot's embedded tracking script on a non-HubSpot website (which many businesses do for CRM, forms, and analytics), you're also getting their cookie consent banner. Sounds great, right? GDPR compliance out of the box!
Except the banner itself loads Google Fonts. Before the visitor has given any consent. Before any cookies are set. The very tool meant to protect privacy is leaking personal data to a third party.
Here's what happens when HubSpot's script loads:
- The
hs-script-loaderJavaScript file is fetched - HubSpot injects a cookie consent banner into the DOM
- As part of rendering the banner, it creates
<link>elements pointing tofonts.googleapis.com - Google receives the visitor's IP address, browser info, and referrer
- The visitor hasn't consented to anything yet
This is not a theoretical problem. In January 2022, the Munich Regional Court (LG München) ruled that dynamically loading Google Fonts violates GDPR because it transmits the user's IP address to Google without consent. The website operator was fined €100 in damages, and that ruling triggered a wave of warning letters across Germany and Austria.
On top of that, HubSpot injects its own <style> tags (hs-banner-style and hs-banner-modal-style) with default CSS that often conflicts with your site's design. So you get both a privacy violation and visual junk.
The Community Has Been Asking for Years # Anchor link
I'm not the first person to notice this. The HubSpot community has multiple threads about it, and none of them have a real solution from HubSpot:
- How to disable Google Fonts - users asking how to stop Google Fonts from loading, no official fix
- HubSpot cookie banner + Google consent mode - discussion about consent mode integration issues
- Disable Google Fonts by embedded Video from YouTube - same problem, different context
- HubSpot Cookie Banner API docs - the API exists, but provides no option to disable font loading
The answer from HubSpot? Silence. Or "use custom CSS to override the styles." That doesn't fix the privacy issue -the request to Google still goes out.
The "We Have a Banner, We're Fine" Problem # Anchor link
Here's the thing that really gets me. This Google Fonts issue is just one symptom of a much bigger disease: cookie banners that do absolutely nothing.
I've seen this firsthand. I once told a business owner that their cookie banner was purely cosmetic - it didn't actually block any cookies, didn't gate any third-party scripts, and didn't comply with GDPR in any meaningful way. His response?
"We have a banner. We're compliant."
— a Biz owner who doesn't understand how GDPR works
No. Having a banner doesn't make you compliant. That's like putting a "No Trespassing" sign on your front door while leaving it wide open.
I wrote about this in detail on FreshJuice: Your cookie banner is probably illegal. The short version: most cookie banners are legal decoration. They sit on websites looking official while cookies fire on page load, third-party scripts track visitors without consent, and Google Fonts leak IP addresses to Mountain View.
And here's the kicker with HubSpot specifically. They actually have a decent Cookie Banner API. It gives you:
addPrivacyConsentListener- to conditionally load scripts based on consentrevokeCookieConsent- to reset consent and remove HubSpot cookiesshowBanner- to let users change their preferences- Granular categories:
analytics,advertisement,functionality
So the API exists. You can properly gate your third-party scripts behind consent categories:
var _hsp = (window._hsp = window._hsp || []);
_hsp.push([
"addPrivacyConsentListener",
function (consent) {
if (consent.categories.analytics) {
// Only now load analytics
}
if (consent.categories.advertisement) {
// Only now load ad pixels
}
},
]);But none of this matters if the banner itself, the very thing asking for consent, is already leaking data to Google via fonts. The API has no option to disable Google Fonts loading. You can't configure it away. There's no disableGoogleFonts: true flag. The font request goes out before your consent listener even fires.
It's like building a security system for your house but leaving the back window open.
Why This Matters # Anchor link
Let's be clear about what's happening: when a browser fetches a Google Font, Google receives:
- The visitor's IP address (personal data under GDPR)
- The User-Agent string (browser, OS, device info)
- The Referer header (which page they're visiting)
- Timing data (when they visited)
After the Munich ruling, this is unambiguously a GDPR violation when done without consent. And a cookie consent banner doing it is... well, peak irony.
But it's not just about legality. It's also about performance. Loading fonts from an external CDN means:
- Extra DNS lookup for
fonts.googleapis.com - Extra DNS lookup for
fonts.gstatic.com - Render-blocking CSS request
- Font files downloaded from yet another origin
All for fonts that your website probably already has loaded, or that the user's system already provides.
The Fix: Intercept and Block # Anchor link
Since HubSpot won't fix this, I did. The solution is a JavaScript snippet that goes before the HubSpot script loader. It uses two techniques:
1. Proxy document.createElement to block Google Fonts at creation time # Anchor link
(function () {
// Proxy createElement to kill Google Fonts links before any network request
var _create = document.createElement.bind(document);
document.createElement = function (tag) {
var el = _create(tag);
if (tag.toLowerCase() === "link") {
// Override the href property setter
var hrefDesc = Object.getOwnPropertyDescriptor(
HTMLLinkElement.prototype,
"href",
);
if (hrefDesc && hrefDesc.set) {
var origSet = hrefDesc.set;
Object.defineProperty(el, "href", {
set: function (v) {
if (
typeof v === "string" &&
v.includes("fonts.googleapis.com")
)
return;
origSet.call(this, v);
},
get: hrefDesc.get
? function () {
return hrefDesc.get.call(this);
}
: undefined,
configurable: true,
});
}
// Also override setAttribute for href
var origSetAttr = el.setAttribute.bind(el);
el.setAttribute = function (k, v) {
if (
k === "href" &&
typeof v === "string" &&
v.includes("fonts.googleapis.com")
)
return;
return origSetAttr(k, v);
};
}
return el;
};
// MutationObserver as a safety net -remove anything that slips through
new MutationObserver(function (mutations) {
for (var i = 0; i < mutations.length; i++) {
for (var j = 0; j < mutations[i].addedNodes.length; j++) {
var n = mutations[i].addedNodes[j];
if (n.nodeType !== 1) continue;
var tag = n.tagName;
// Remove Google Fonts links
if (
tag === "LINK" &&
n.href &&
n.href.includes("fonts.googleapis.com")
) {
n.remove();
continue;
}
// Remove HubSpot's default banner styles (optional -if you want to use your own)
if (
tag === "STYLE" &&
(n.id === "hs-banner-style" ||
n.id === "hs-banner-modal-style")
) {
n.remove();
}
}
}
}).observe(document.documentElement, {
childList: true,
subtree: true,
});
})();2. Place it before HubSpot's script # Anchor link
<!-- Block Google Fonts and HubSpot default styles -->
<script>
// ... the script above ...
</script>
<!-- HubSpot Embed Code -->
<script
type="text/javascript"
id="hs-script-loader"
async
defer
src="//js-eu1.hs-scripts.com/YOUR_ID.js"
></script>The order matters. The proxy must be in place before HubSpot's script starts executing and creating DOM elements.
How It Works # Anchor link
The createElement proxy intercepts every <link> element HubSpot tries to create. Before the element can be inserted into the DOM (and trigger a network request), it checks if the href points to fonts.googleapis.com. If it does, the setter silently returns without setting the value. No URL = no network request = no IP leak.
The MutationObserver is a safety net. It watches the entire document for new nodes. If a Google Fonts link somehow slips through the proxy (maybe via innerHTML or a different code path), the observer catches it and removes it immediately.
The style removal (hs-banner-style and hs-banner-modal-style) is optional but recommended. HubSpot injects default CSS that often clashes with your site's design. Removing these lets you style the consent banner with your own CSS that matches your site. You can skip this part if you're fine with HubSpot's default appearance.
The Better Alternatives # Anchor link
Beyond fixing HubSpot's mess, here's what you should be doing with fonts in general:
Self-Host Your Fonts # Anchor link
Download the font files and serve them from your own domain. No third-party requests, no IP leaks, better caching control.
@font-face {
font-family: "Inter";
src: url("/fonts/inter-var.woff2") format("woff2");
font-display: swap;
}Use Bunny Fonts # Anchor link
If self-hosting feels like too much work, Bunny Fonts is a drop-in replacement for Google Fonts. Same API, same fonts, but:
- Zero tracking -no IP logging, no cookies
- EU-based company and infrastructure
- GDPR compliant by design
- No account needed, always free
The migration is literally a find-and-replace:
- https://fonts.googleapis.com/css2?family=Inter
+ https://fonts.bunny.net/css2?family=Inter
That's it. Same URL structure, same font files, zero privacy issues.
Use System Fonts # Anchor link
The most performant option? Don't load any web fonts at all:
body {
font-family:
system-ui,
-apple-system,
"Segoe UI",
Roboto,
"Helvetica Neue",
Arial,
sans-serif;
}System fonts are already on the user's device. Zero network requests. Instant rendering. And they look native to the platform, which many users actually prefer.
The Bigger Picture # Anchor link
This isn't just about HubSpot. It's about a mindset problem in the web industry:
Third-party tools shouldn't load their own fonts. If a tool injects UI into your website (cookie banners, chat widgets, analytics dashboards), it should use the fonts already available on the page or fall back to system fonts. Loading Google Fonts for a cookie banner that displays two sentences of text is absurd.
Privacy-first means privacy always. A consent mechanism that violates privacy before consent is given defeats its own purpose. If HubSpot can build a complex consent management system, they can certainly avoid loading Google Fonts from a third-party CDN.
Performance matters. Every external resource is a potential point of failure, an extra DNS lookup, and wasted bandwidth. Cookie banners should be lightweight. They should appear instantly. Loading external fonts for cosmetic reasons is the opposite of lightweight.
TL;DR # Anchor link
- HubSpot's cookie consent banner loads Google Fonts before consent, leaking visitor IPs to Google
- This violates GDPR (see: Munich court ruling, €100 fine)
- The HubSpot community has asked about this for years with no official fix
- You can fix it by proxying
document.createElementand using aMutationObserverto block Google Fonts requests - Better yet: self-host your fonts, use Bunny Fonts, or just use system fonts
- Privacy tools should not violate privacy. Full stop.
May the 4th be with you,
Alex