HubSpot CMS mobile page speed optimization

Hi everyone,

I have a HubSpot CMS page where the content is the same on both desktop
and mobile - I’m not hiding any sections or elements on mobile, everything
that shows on desktop also shows on mobile.

My question is: since I can’t reduce or hide content on mobile, what are
the best mobile-specific optimization techniques I can apply to improve
mobile PageSpeed score, without removing anything visually?

I’ve already done the following:

  • Converted images to WebP
  • Added lazy loading on images
  • Added width and height on all images
  • Compressed video sizes
  • Cleaned up JS and CSS (no duplicate or unused files)
  • Added preconnect tags
  • Optimized for mobile as much as possible from my side

Even after this, my mobile score is around 30-40, while desktop is much
higher.

Questions:

  1. What other mobile-specific optimizations can I apply, keeping the same
    content structure as desktop (no hiding/removing sections)?
  2. Is there a realistic maximum mobile score achievable on HubSpot CMS,
    given that some scripts (forms, reCAPTCHA, tracking) are managed by
    the platform and can’t be modified?
  3. Is 80+ on mobile achievable while keeping full desktop-equivalent
    content, or does that typically require reducing content or building
    a custom lightweight theme?

Would appreciate insights from anyone who has dealt with this. Thanks!

Hey Arjun, I completely understand how frustrating it is when you cannot remove content on your phone.

There are a things that you can try to make your website load faster on mobile. First you should put your CSS at the top of the page and load the rest of the CSS after that. This is because CSS can block the rendering of the page.

Here are some other things you can try:

  • Put your CSS at the top of the page and load the rest of the CSS after that

  • Use defer on any JavaScript that you control

  • Check that all of your images are the size for mobile phones not just compressed versions of the big images. Sometimes people just compress the images without checking if they are still too big for phones.

  • If you are using custom fonts you should preload them. You should also check the console for any warnings about text.

If you are not using Boilerplate you might want to try using a template to see if it loads CSS and JavaScript efficiently.

I also wanted to talk about the script that you were asking about. The scripts that HubSpot uses for forms and tracking and reCAPTCHA can really slow down your website. You cannot remove these scripts. You can try loading them when the user scrolls to that part of the page instead of when the page first loads. This helped me a bit. My mobile score is still pretty low 65 but my desktop score is in the 90s.

I do not think it is possible to get a score of 80 or higher with a website, at least not without doing a lot of work. If someone has been able to do it I would love to hear how they did it.

Thank you for sharing your experience, this is really helpful!

I wanted to ask - in my case, desktop score is 90+ but mobile is stuck
around 50, and LCP specifically is very high (14.2s) on mobile. Could you
help me understand why the gap between desktop and mobile is this large?
Is this mainly due to network/CPU throttling in the test, or is there
something specific I might be missing?

Also, regarding TBT and LCP - since HubSpot’s default scripts (forms.js,
reCAPTCHA, and other platform-level scripts) load automatically on the
page and we can’t modify, defer, or remove them, how much of an impact
do these have on the overall score? If these scripts are unavoidable, is
there a realistic ceiling on how high the mobile score can go, regardless
of how much we optimize on our end?

I’ve already implemented the following on my page:

  • Compressed and converted all images to WebP
  • Added lazy loading and correct width/height on images
  • Deferred JS I control (GSAP, ScrollTrigger, slick.js)
  • Preloaded custom fonts
  • Cleaned up unused/duplicate JS and CSS
  • Working on removing the background video on mobile specifically
    (replacing with image + content)

Given that the forms/reCAPTCHA scripts are HubSpot-managed and can’t be
touched, and I’ve optimized everything else on my side, do you think 80+
is a realistic target on mobile, or should I be aiming closer to the
65-70 range like you mentioned? Would really appreciate your honest take
based on your experience.

Thanks again for taking the time to help!

Hey @arjunkhankriyal and welcome, it’s a pleasure to have you here!

Great question, thanks for asking the HubSpot Community!

To add to what @AGupta58 shared (thank you!), I’d suggest checking this documentation that can help: Optimizing your HubSpot CMS site for speed - HubSpot docs .

Here are additional optimizations you could apply:

  • Decoding=“async” on images, it lets the browser load other content in parallel while processing images.
  • Limit tracking scripts, each one compounds the performance cost significantly on mobile.
  • For autoplaying video, show a fallback image on mobile instead of loading the video (which it seems you are working on at the moment).

Now, let’s consult our Top Experts: Hi @AGupta58, @Anton and @evaldas can you think of other optimizations that @arjunkhankriyal could put in place, please?

Thanks so much and have a wonderful weekend!
Bérangère

This post was created with the assistance of AI tools

Hey @arjunkhankriyal,

my personal approach is creating/using only custom modules and custom themes (I’ve created my own boilerplate for this).

Depending on the clients requirements this can be quite a task, but this allows you to fully dig into every little bit of code and work on a whole different level of granularity.

My best friends for such are if-statements/booleans, choice-fields, variables and often export_to_template_context as well as

A practical example:

If I’m building something simple like an accordion, I’m putting the static JS part into something like an accordion.js file in my theme and referencing it with the require_js function (I like to keep all JS/CSS in one place rather than using module.js/module.css).

Then is the CSS - not as a high impact on performance - but this still can sum up.

If the module got tons of styling options, I don’t need everything to load every time - therefore I’m wrapping corresponding parts in if-statements and choice-fields like

{% require_css %}
<style>
{% scope_css %}
.module{
border: 5px solid red
{{module.styles.padding.css}}
}

{% if module.some_choice == "option_a"%}
.module.option_a{
background-color: {{module.styles.background-color.css}};
}

{% elif module.some_choice == "option_b" %}
.module.option_b{
border-color: {{module.styles.background-color.css}};
}
{% end_scope_css %}
</style>
{% end_require_css %}

...

<div class="module {{module.some_choice}}">
your content 
</div>

You can do something similar to JS (only in module.html or templates)

{% require_js %}
<script>
{% if module.some_choice == "option_a"%}
//some script which should be applied when option A is selected
{% elif module.some_choice == "option_b" %}
//some script which should be applied when option B is selected 
</script>
{% end_require_js %}

There are countless options here - just be a bit creative and think this way:
Anything that is an “if question” can be put into an if- or unless-statement. Different options are choice-fields.
Build the whole structure with it (don’t forget to use comments in the code)

Reusable blocks accross modules can be put into macros

If you want to learn more about such approaches, we/the Developer HUG had a great event about Mastering HubL (YouTube recording) a while ago.

As for the realistic maximum achievable mobile score: Yes, 100% :wink:

It’s a ton of work, but possible. Two years ago, when I launched my website (graphispot.com) I’ve set my own goal to optimize it to 100% on mobile and desktop. Honestly - it was quite a lot of work.

Since then, Google has changed their Lighthouse algoritm and because of this, my performance dropped from 100 to around 65/70. For now, I’m fine with it as I’m already working on a new website/theme.

Reducing the content on mobile is an option to optimize for performance, but not the best UX. Neither for the business, nor for the visitor.

My recommendation is to replace videos with linked images which trigger the video (or lead to the externally hosted video), forms is something we’ve discussed in the other topic.

But honestly - don’t rely on the numbers. A blazing fast website, can be so fast that the performance will show you some bad scores.

Just do some real-life tests. Grab a mobile device, open the URL and see if there are some layout-shifts or something you can actually optimize.

Hope this helps

best,
Anton

Hi there!

I can usually improve mobile PageSpeed scores to around 75–85/100. All the points you mentioned are important, so you’re definitely looking in the right direction.

I’d recommend starting by checking the biggest bottlenecks identified in Google PageSpeed Insights. Without seeing the actual report, it’s difficult to give specific recommendations, but these are the areas I would review first:

  1. Make sure images are properly resized and optimized for mobile devices, for example by using srcset.

  2. Check how tracking and analytics scripts are loaded, as they can significantly slow down the website.

  3. Defer non-critical JavaScript to prevent it from blocking the initial page load.

  4. Disable or remove any unnecessary built-in HubSpot features that are not currently being used.

The PageSpeed Insights report should help identify which of these areas has the greatest impact and should be addressed first.

Hi Anton ,

Thanks again for the detailed inputs above — really helped me understand the areas to focus on.

I’ve implemented several of the suggestions (image optimization, lazy loading, JS defer, etc.) and here’s my current live homepage: https://www.markivis.com/

Desktop score is 80+, but mobile is still lagging behind. Would you be able to take a quick look and point out what’s specifically holding mobile back for this page? Any insight on realistic next steps would mean a lot.

Thanks for your time!

Best,
Arjun

Thanks for the suggestions.

The website I’m currently optimizing is https://www.markivis.com/. Could you please take a quick look and let me know if you notice any major performance bottlenecks or HubSpot CMS-specific optimizations that could help improve the mobile PageSpeed score?

Hey @arjunkhankriyal,

a few ideas:

add a lazy load to your videos.
Gallery-cards (our videos) got no lazy-load and got a preload (which might impact the loading).
If you want to control if a lazy load should be added or not, you can add a boolean to the module (or repeater item and write it like this)

Code for per-item control (boolean is in the item):

{% for item in module.gallery_cards %}
   {% if item.add_lazy_load %}
      {% set lazy_load = "loading=" ~ "lazy" %}
   {% endif %}

   <div class="gallery-card">
      <img>
      <video {{lazy_load }}>
         <source src="{{item.video.src}}">
      </video>
   </div>

Code for module wide control (boolean is outside the repeater):

{% for item in module.gallery_cards %}
   {% if module.add_lazy_load %}
      {% set lazy_load = "loading=" ~ "lazy" %}
   {% endif %}

   <div class="gallery-card">
      <img>
      <video {{lazy_load }}>
         <source src="{{item.video.src}}">
      </video>
   </div>

You should also add a fetchpriority=“low” to it as it’s not above-the-fold.

Or simply remove it with a small javascript on smaller screens like

{% for item in module.gallery_cards %}
...
{% endfor %}

...

{% require_js %}
<script>
document.addEventListener("DOMContentLoaded", () => {
  const isMobile = window.matchMedia("(max-width: 767px)"); // set the screen-size the video should be removed from the DOM entirely 

  function checkScreenSize() {
    if (isMobile.matches) {
      const videos = document.querySelectorAll('.gallery-card video');
      
      videos.forEach(video => {
        video.remove(); 
      });
    }
  }

  checkScreenSize();
});
{% end_require_js %}

p.s - this script will be loaded by module instance - if you want to have it globally, just put in your main.js

Google page speed displays that you got GSAP, jQuery and ScrollTrigger. You’re also using Animate on scroll.

If you don’t rely on jQuery, remove it from the theme and check, if it’s disabled in the pages settings.

ScrollTrigger is a GSAP Plugin.

IMO, you got AOS and GSAP+ScrollTrigger which results in a somewhat double setup.

I’d also recommend to remove the video in the hero on mobile and replace it either with an image or plain text.

This video got fetchpriority=“low” which most likely result in a layout shift as it’s an above-the-fold element.

Another element I see from the DOM is that the header partial/module is load font-awesome just above the element rather than in the header.

Just wrap it in a require_css block or move it to something like the header.html

best,
Anton

As I though you have to work on scripts loading.

In era of AI you don’t need to load jquery 1.7.1 from HubSpot Website settings. You can convert jquery to javascript easily.

gsap.js - try to defer loading that script.

gtag manager - try to load it after user accept cookies or after 5-6s+

you can also try to lazy load videos that are being played inline.

If it helped please select my comment as a solution :slight_smile: