Site Speed
Resources
<!-- Remove Animation CSS on mobile -->
<link rel="stylesheet" href="/css/animate.css" media="screen and (min-width: 992px)">
<!-- Add before google fonts -->
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<!-- Add above Master.js -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.0/lazysizes.min.js"></script>
<!-- Only add if using Object-fit property -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/object-fit-images/3.2.4/ofi.min.js" type="text/javascript"></script>
<!-- Replace scrollfire JS with CDN version for faster loading -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery.scrollfire/1.4.0/jquery.scrollfire.min.js"></script>
<!-- Set all scripts to defer except for jQuery -->
CSS
/* Fallback for preventing grade.us from loading twice in case you accidentally miss any grade.us scripts */
.reviewmgr-stream div ~ div { display: none; }
/* Use class="cover" on images to fit to parent container without stretching/warping images - great replacement for background images (Requires Polyfill) */
img.cover { object-fit: cover; font-family: 'object-fit: cover;'; width: 100%; height: 100%; }
/* Fade image in after lazyloaded */
.lazyload, .lazyloading { opacity: 0; }
.lazyloaded { opacity: 1; transition: opacity 300ms; }
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")
}
}
}
);
//lazyload support for background images - add class lazyload and data-bg="/images/image-name.jpg" to container instead of CSS
document.addEventListener('lazybeforeunveil', function(e){ var bg = e.target.getAttribute('data-bg');
if(bg){
e.target.style.backgroundImage = 'url(' + bg + ')';
}
});
// Load Grade.Us on Scroll - remove grade.us script from HTML
$('.reviewmgr-stream:not(.gradeus-loaded)').scrollfire({
offset: 0,
topOffset: 0,
bottomOffset: -500,
onScroll: function (elm, distance) {
if ($('.gradeus-loaded').length < 1) {
!function (d, s, id) {
var js,
fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.grade.us/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "gradeus-wjs");
$(elm).addClass("gradeus-loaded");
}
}
});
// Load Reputation on Scroll - remove Reputation widget script tag from HTML
$('.reputation-widget:not(.reputation-widget-loaded)').scrollfire({
offset: 0,
topOffset: 0,
bottomOffset: -500,
onBottomIn: function (elm, distance) {
if ($('.reputation-widget-loaded').length < 1) {
!function(d,s,c){
var js,fjs=d.getElementsByTagName(s)[0];
js=d.createElement(s);
js.className=c;
js.src="https://widgets.reputation.com/src/client/widgets/widgets.js?v=1592944030435";
fjs.parentNode.insertBefore(js,fjs);
}(document,"script","reputation-wjs");
$(elm).addClass("reputation-widget-loaded");
}
}
});
// 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");
}
}
});
//Polyfill for Object Fit Images
objectFitImages('img.cover');
Hide Chat on Mobile Javascript
// 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);
});
HTML
Lazyloading Images & Iframe
Add class="lazyload" and change all src to data-src for all images and iframes below the fold.
Lazyloading Background Images
Add class="lazyload" and data-bg="/images/image-name.jpg" to container. Remove background-image from CSS.
Grade.Us
Remove all Grade.Us scripts
LiveChat
Add class="lazy-chat" to the body tag of any template you need the chat to load
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.
Blog - Inline Template
Lazyload any featured images & iframes
{%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%}
Large Images (above the fold)
Create Mobile versions of banner images at 500px wide
@media (max-width: 500px){
#home-banner { background-image: url('/images/home-banner-mobile.jpg');}
}
Optimize large images above the fold including FB Offer Images
Hidden Vcard Images
If hidden Vcard images are showing up on PageSpeed Insights, make sure to change it from img to object
<object class="photo" itemprop="image" data="/images/social-sharing.jpg" type="image/jpg">social sharing</object>