Site Speed

Lazyloading

How to Lazyload Everything!


Getting Started

Make sure that lazysizes.js has been added to your Resources Snippet

            
            
            
            <script defer src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js" integrity="sha512-q583ppKrCRc7N5O0n2nzUiJ+suUv7Et1JGels4bXOaMFQcamPk9HjdUknZuuFjBNs7tsMuadge5k9RzdmO+1GQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
            
            
          

Lazysizes Unveilhooks Extension

The unveilhooks plugin extends lazySizes to also unveil / lazyload scripts/widgets, background images, styles and video/audio elements.

Please Note: This extension code has already been added to the bottom of the master.js on newer templates.

            
            
            
            <script defer src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/plugins/unveilhooks/ls.unveilhooks.min.js" integrity="sha512-hQ7LIAYhD17CZh6bDzdQI7NThUHmZGcAbGDfCWHO/sOEPRAdlkQFg4gTsKhWWbI1PMUvjD7JjA+5x3pH23Bnyg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
            
            
          

CSS (optional)

Add an animation to fade in image after lazyloaded

    			
    				.lazyload, .lazyloading { opacity: 0; }
    				.lazyloaded { opacity: 1; transition: opacity 300ms; }
    			
    			

How to Use LazySizes

LazySizes is the ultimate and lightweight lazyLoader which lazy loads images (including responsive images (picture/srcset)), iframes and scripts.

Simply add class="lazyload" and change all src to data-src for all images and iframes below the fold.

Make sure to lazyload every image and iframe below the fold!

Images

            
              
              
              <img class="lazyload" data-src="/images/your-image.jpg" alt="Your Image">
              
            
          

iFrames

This can be used on any iframe (videos, maps, widgets, etc.)

            
              
              
              <iframe class="lazyload" data-src="https://www.youtube.com/embed/NpEaa2P7qZI"></iframe>
              
            
          

Background Images

Add class="lazyload" and data-bg="/images/image-name.jpg" to the element you want the background image to appear.

** Remove background-image url from CSS.

            
              
              
              <section class="lazyload" data-bg="/images/image-name.jpg">
                <!-- [ content goes here ] -->
              </section>
              
            
          

Scripts/Widgets

            
              
              
              <div class="lazyload" data-script="/js/script-name.js">
                <!-- [ content can go here ] -->
              </div>
              
            
          

CSS

            
              
              
              <div class="lazyload" data-link="/css/my-style.css">
                <!-- [ content can go here ] -->
              </div>
              
            
          

CSS & Scripts Combined

            
              
              
              <div class="lazyload" data-script="/js/script-name.js" data-link="/css/my-style.css">
                <!-- [ content can go here ] -->
              </div>
              
            
          

Blogs

Lazyload featured images & iframes on blogs

            
              
              {% if post.featuredImageUrl contains 'youtu' %}
                <div class="video-wrapper">
                  <iframe class="lazyload" title="{{ post.title }}" data-src="{{ post.featuredImageUrl | replace: 'youtu.be/', 'youtube.com/embed/' | replace: 'watch?v=', 'embed/' }}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
                  <span class="sr-only">Video</span>
                </div>
              {% elsif post.featuredImageUrl contains '.jpg' or post.featuredImageUrl contains '.png' or post.featuredImageUrl contains '.gif' or post.featuredImageUrl contains '.jpeg'  %}
                <div class="post-image">
                  <img class="lazyload" data-src="{{ post.featuredImageUrl }}" alt="{{ post.title }}" width="100%">
                </div>
              {% endif %}
              
            
          

Vcard Images

Hidden Vcard images may still show up on PageSpeed Insights even if lazyloaded, make sure to change it from <img> to <object> instead:

            
              <object class="photo" itemprop="image" data="/images/social-sharing.jpg" type="image/jpg">social sharing</object>
            
          
View Full lazySizes Guide >

Image Optimization

Alway optimize ALL of your images! This even includes FB Offer Images & social sharing images.

Resizing Your Images

Make sure to save the image as close as possible to the same size that it will be displayed on your site.
Example: if your image will be 900px wide, save your image at 900px wide.

Full-width Background/Banner images are typically saved at 2000px. Please also create a cropped mobile version of background images at 500px wide.

Compress Your Images

There are multiple ways to reduce your image file sizes:

  • If you have Photoshop, make sure to use "Save for Web". You can find it in the upper menu under File > Export > Save for Web (Legacy) or use the keyboard shortcut option + shift + command + s

  • If you don't have photoshop, there are many online image compressors available online. Here is one below:

    Online Image Compressor >

Large Images (above the fold)

Create Mobile versions of banner images at 500px wide and use CSS to swap the image on moble devices:

            
              @media (max-width: 500px){
                #home-banner { background-image: url('/images/home-banner-mobile.jpg');}
              }
            
          

Google PageSpeed Insights

How to Make Sense of it all


More Info Coming Soon!

Resources Snippet

How to Optimize Your Resources Snippet


Preconnect & DNS Prefetch

Make sure that to add a preconnect for fonts. This can be used for Google Font or Adobe Font. Add a dns-prefetch to your CDN

Google Fonts
              
              
              
              <link rel="preconnect" href="https://fonts.googleapis.com">
              <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
              
              
            
Adobe Fonts
              
              
              
              <link rel="preconnect" href="https://use.typekit.net" crossorigin>
              <link rel="preconnect" href="https://p.typekit.net" crossorigin>
              <link rel="preload" href="https://p.typekit.net" crossorigin>
              
              
            
CDN
              
              
              
              <link rel="dns-prefetch" href="https://cdnjs.cloudflare.com" crossorigin>
              
              
            

Fonts

Make sure to only load the font and it's specific weights that the site is actually using.

Example of too many font weights (don't do this!):
              
                
                
                <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
                
              
            
Your font url should only contain what you need!
              
                
                
                <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
                
              
            

Animations

Make sure that the animation.css only loads on mobile by adding media="screen and (min-width: 992px)"

							
							<link rel="stylesheet" href="/css/animate.css" media="screen and (min-width: 992px)">
							
						

Lazy Animations

Sometimes animations are called "lazy". This does not affect site speed.

"Lazy animations" is just another way to refer to scroll-triggered animations where the animations don't play until the user scrolls down.

Learn More About Lazy Animations >

Scripts

Defer every script tag (except for jquery)

Please Note: Deferring jQuery will break Nesthub forms!

Use the same CDN for all external Script files

The example below is using https://cdnjs.cloudflare.com Search for scripts on cdnjs >

							
							
							
							<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha512-+NqPlbbtM1QqiK8ZAo4Yrj2c4lNQoGv8P79DPtKzj++l5jnN39rHA/xsqn8zE9l0uSoxaCdrOgFs6yjyfbBxSg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
							<script defer src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.bundle.min.js" integrity="sha512-i9cEfJwUwViEPFKdC1enz4ZRGBj8YQo6QByFTF92YXHi7waCqyexvRD75S5NVTsSiTv7rKWqG9Y5eFxmRsOn0A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
							<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery.scrollfire/1.4.0/jquery.scrollfire.min.js"></script>
							<script defer src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
							<script defer src="https://kit.fontawesome.com/8e7537a24b.js" crossorigin="anonymous"></script>
							<script defer src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.0/lazysizes.min.js"></script>
							<script defer src="https://www.google.com/recaptcha/api.js?onload=onIonRecaptchaLoad&render=explicit"></script>
							<script defer src="/js/master-v3.js?v2"></script>
							
							
						

Lazyload LiveChat

Add the Javascript below and then add class="lazy-chat" to the body tag of any template (or specific page) you need the chat to load

Make sure to update the license number in the Javascript to match the client's LiveChat license ID


Javascript

Standard Version

              

                // Load Chat on Scroll - Make sure to update Lazy Chat ID code in JS with the client's LiveChat ID
                $('.lazy-chat:not(.chat-loaded)').scrollfire({
                  offset: 0,
                  topOffset: 0,
                  bottomOffset: -500,
                  onScroll: function (elm, distance) {
                    if ($('.chat-loaded').length < 1) {
                      window.__lc = window.__lc || {};
                      window.__lc.license = 11083912; // <--- Update ID Here
                        // window.__lc.chat_between_groups = false;  <--- add for Homeriver only
                      (function () {
                        var lc = document.createElement('script');
                        lc.type = 'text/javascript';
                        lc.async = true;
                        lc.src = (
                          'https:' == document.location.protocol
                            ? 'https://'
                            : 'http://'
                        ) + 'cdn.livechatinc.com/tracking.js';
                        var s = document.getElementsByTagName('script')[0];
                        s.parentNode.insertBefore(lc, s);
                      })();
                      $(elm).addClass("chat-loaded");
                    }
                  }
                });
              
            

Hidden Chat on Mobile Version

    				

    					// Lazy chat - no mobile
    $(document).ready(function() {
        var $window = $(window);
        function checkWidth() {
            var windowsize = $window.width();
            if (windowsize > 500) {
                // Load Chat on Scroll - Make sure to update Lazy Chat ID code in JS with the client's LiveChat ID
    $('.lazy-chat:not(.chat-loaded)').scrollfire({
    	offset: 0,
    	topOffset: 0,
    	bottomOffset: -500,
    	onScroll: function (elm, distance) {
    		if ($('.chat-loaded').length < 1) {
    			window.__lc = window.__lc || {};
    			window.__lc.license = 11083912; // <--- Update ID Here
    			  // window.__lc.chat_between_groups = false;  <--- add for Homeriver only
    			(function () {
    				var lc = document.createElement('script');
    				lc.type = 'text/javascript';
    				lc.async = true;
    				lc.src = (
    					'https:' == document.location.protocol
    						? 'https://'
    						: 'http://'
    				) + 'cdn.livechatinc.com/tracking.js';
    				var s = document.getElementsByTagName('script')[0];
    				s.parentNode.insertBefore(lc, s);
    			})();
    			$(elm).addClass("chat-loaded");
    		}
    	}
    });
            }
        }
        // Execute on load
        checkWidth();
        // Bind event listener
        $(window).resize(checkWidth);
    });
    	
    

Lazyload Reputation Widgets

This can be done easily by using LazySizes!

Learn more about LazySizes >

Grade.Us

Remove all separate Grade.Us scripts, insert data-script="//platform.grade.us/widgets.js" and add class="lazyload"

    				
              
              
              <div class="reviewmgr-stream lazyload" data-script="//platform.grade.us/widgets.js" data-include-empty="false" data-last-initial="true" data-review-limit="3" data-url="https://reviews.nesthub.com/testing-pm/"></div>
              
    				
    			

Reputation

This can be done basically the same way as above.

Remove all separate Reputation scripts, insert data-script="https://widgets.reputation.com/src/client/widgets/widgets.js" and add class="lazyload" to the widget code that was copied from Reputation.com

FRS

If there is an FRS widget on the page, FRS will automatically load. If you have an FRS widget below the fold (example: properties widget on Home Page), add class "lazy-frs" to the section containing the FRS widget to prevent FRS from loading until you scroll to that section.

Javascript

    				
    					// Replace FRS API Script
    					function loadFrs() {
    					  (function(d, s, id, k) {
    						var js, fjs = d.getElementsByTagName(s)[0];
    						if (d.getElementById(id)) return;
    						js = d.createElement(s);
    						js.id = id;
    						js.src = "//www.freerentalsite.com/widgets/v2/?apiKey=" + ((k) ? encodeURIComponent(k) : '');
    						fjs.parentNode.insertBefore(js, fjs);
    					  }(document, 'script', 'frs-jssdk', null));
    					};

    					// Only Load FRS if FRS Widget is on Page or if class lazy-frs is present
    					if ($('[data-frs]').length > 0 && $('.lazy-frs').length == 0) {
    					  loadFrs();
    					};


    					// Trigger FRS on Scroll - add class lazy-frs to FRS widget containers on Home Page
    					$('.lazy-frs:not(.frs-loaded)').scrollfire(
    						{
    							offset: 0,
    							topOffset: 0,
    							bottomOffset: -500,
    							onScroll: function (elm, distance) {
    								if ($('.frs-loaded').length < 1) {
    									loadFrs();
    									$(elm).addClass("frs-loaded")
    								}
    							}
    						}
    					);