Working on mobile PageSpeed optimization for two HubSpot CMS pages and stuck despite doing most standard fixes. Target is 70+ on mobile, without hiding or removing content.
All images converted to WebP with proper width/height attributes
Animations disabled on mobile viewport
Non-critical JS deferred wherever possible
Forms lazy-loaded so reCAPTCHA/forms.js doesn’t block initial load
loading="lazy" and fetchpriority set appropriately on images
Has anyone gotten HubSpot CMS mobile scores from 30s to 70+? What made the biggest difference — any HubSpot-specific approach (not generic web-perf tips) would help a lot.
Testing it on my smartphone - the page is quite fast and doesn’t correspond to the pagespeed number.
A few things I’d change are:
close the HubSpot accordion in the “Explore Our Marketing Automation Ecosystem” section or remove the AOS at least as closing it as a user results in a loading period of the other accordion items.
Rebuild the “FAQ” section next to the form. The overflow/scroll isn’t a great UX. I’d just put it above/below the form as a whole.
You got basically the same accordion JS getting loaded twice on the Marketing automation Services page. One in the “Explore Our Marketing Automation Ecosystem” accordion and one in the FAQ. As it’s basically the same script, I’d remove it from the modules and put it into the main.js (or what ever your main js file is called)
If your theme don’t rely on jQuery - disable it globally in the settings
If your portal is located on the na1 server (north america 1), it might be affected by the current partial outage (status.hubspot.com)
@Anton’s already covered the accordion/duplicate-script side well, so I won’t repeat that. Regardless of what else you fix, this is worth doing.
One thing I’d add, based on going through your pages directly in DevTools (Network tab, throttled to 3G) rather than just the PageSpeed summary: your reCAPTCHA isn’t actually deferring the way it looks like it should. It’s sitting as a global script in the <head> and initializes on page load, not when the form scrolls into view. Under 3G, the reCAPTCHA anchor iframe, bframe iframe, and their reload request were chained together and took close to 7 seconds on their own, before the user had even reached the form. That’s a big chunk of your load time going to something nobody’s interacted with yet.
Two smaller things worth a quick check on top of that:
You’re loading two separate font services at once, Google Fonts and Adobe Fonts (Typekit), both active on the same page. Two font pipelines means two extra connections for something you only need one of.
Open DevTools > Coverage tab and reload the page. It’ll show you the % of your theme’s CSS/JS that’s actually unused on that page. If it’s high, that tells you the weight is coming from the theme bundle itself rather than from page content, which changes where you look next. Ran Coverage on https://www.markivis.com/marketing-automation-services (DevTools > Coverage tab > reload) And here’s what came back:
Hi @arjunkhankriyal
To add to the great advice already in this thread,
You’ve already covered most of the optimizations I would normally suggest. At this point, I’d focus on your custom modules and any third-party scripts, as they’re often the biggest reason mobile scores stay low.
I’d also check if every CSS and JS file is actually needed and only loading on pages where it’s used. If the page has a lot of nested sections or modules, simplifying the structure can help a bit too.
In my experience, getting from the 30s to 70+ is usually about making lots of small improvements rather than finding one big fix.
I hope this helps you out. Please mark it as Solution Accepted and upvote to help another Community member.
Thanks for breaking this down into clear steps. As someone who’s still learning HubSpot CMS optimization, it’s helpful to understand how to separate theme-related issues from page-specific ones. I’ll definitely keep an eye on the suggestions in this thread.
It sounds like you’ve already worked through most of the optimizations I’d normally suggest, so I think you’re at the stage where it’s more about identifying the remaining bottlenecks than applying more generic tweaks.
One thing I’d look at is your third-party integrations. Even when scripts are deferred, things like analytics, tag managers, cookie banners, or chat widgets can still add to Total Blocking Time on mobile. I’ve had good results by testing them individually to see if one is having a bigger impact than expected.
Also spend a bit of time reviewing the hero section. Even with optimized images, elements like multiple fonts, background media, or a complex layout can affect LCP. Sometimes a few small adjustments above the fold make more difference than expected.
If you’re using custom modules, it’s also worth checking whether every CSS and JavaScript asset needs to load immediately. In a few projects I’ve worked on, reducing the amount of code needed for the initial page render helped improve mobile performance without changing the page content.
Since you’ve already taken care of image optimization, lazy loading, deferred JavaScript, and form loading, I’d rely on the PageSpeed diagnostics to guide the next round of optimizations rather than trying more general fixes. In my experience, once you’ve reached this point, it’s usually one or two specific resources that are holding the score back.
If you end up finding that dynamic script loading or complex asset optimization is still dragging down your mobile scores, automated tools like Website Speedy can also help streamline third-party script and asset loading without having to manually refactor your codebase. (Disclaimer: I’m affiliated with Website Speedy).
A few things not mentioned yet in this thread that are worth checking:
Srcset, not just WebP + width/height. HubSpot only auto-generates a srcset through the built-in image module or img_url/image_tag filters with sizes set. If any images are custom-coded <img> tags with one hardcoded src, mobile is downloading the same file as desktop, just shown smaller. Check DevTools on mobile view for a missing srcset attribute, that’s often why “Properly size images” still fails after WebP.
theme.json, not just page content. If the unused CSS/JS shown in Coverage traces back to sliders, accordions, or animation libraries declared as global requires in theme.json, every page loads that code even where it’s not used. Scoping those requires to the specific templates/modules that need them is the actual fix, not just removing one duplicate script.
Check for a proxy in front of HubSpot’s CDN. If the domain sits behind Cloudflare or similar, confirm the DNS record is DNS-only. HubSpot CNAMEs generally reject full proxying outside CMS Enterprise + Cloudflare Enterprise O2O, so an accidental proxy adds a hop before the request even reaches HubSpot’s own CDN.
reCAPTCHA and the duplicate JS Anton and muujeeb flagged are still the bigger wins first. These three are the next layer once those are fixed.