Fix a crowded mobile heading
Check the native settings before adding a custom rule.
2 shared labelsFree tool · Squarespace 7.1 blogs
Match related posts by shared tags, categories, or both. Choose the layout, then generate code for your blog.
Configure your related postsStart with the native option
Squarespace Summary Blocks can show posts from a category or tag you choose. Use this generator when you want recommendations to change with each article.
Compare the native and automatic optionsExample content, not your live blog
Tags: Typography, Tutorial
Category: Design
Check the native settings before adding a custom rule.
2 shared labelsKeep the important part of an image visible on a phone.
2 shared labelsGive visitors a clear way to find the next useful answer.
1 shared labelShared labels determine the order. Equal matches use newest first, then the URL. Results can be fewer than your maximum. The current article is excluded.
<!-- Squarespace Tools Related Posts v2. Replace the older export; paste once in site Footer Code Injection.
Squarespace 7.1 blog posts only. Up to 10 feed pages / 300 posts. A changing Squarespace JSON representation is used, not a supported stable API.
If the collection cannot be read completely within these limits, no recommendations are shown. -->
<style>
.sqt-related{margin:3rem 0;max-width:100%;color:inherit}
.sqt-related *{box-sizing:border-box}
.sqt-related h2{font-size:clamp(1.4rem,3vw,2rem);line-height:1.2;color:#234c3c;margin:0 0 1.5rem;overflow-wrap:anywhere}
.sqt-related-items{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,220px),1fr));gap:1.25rem}
.sqt-related-card{min-width:0;display:flex;flex-direction:column;text-decoration:none!important;color:inherit!important;overflow:hidden;border-radius:8px;background:#fff;border:1px solid #d6ddd5;}
.sqt-related-card:focus-visible{outline:3px solid #234c3c;outline-offset:4px}
.sqt-related-card img{width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;display:block}
.sqt-related-body{padding:1rem;min-width:0;overflow-wrap:anywhere}
.sqt-related h3{font:inherit;font-size:1.1rem;font-weight:600;line-height:1.4;margin:0;color:#203c30}
.sqt-related-card:hover h3{text-decoration:underline;text-underline-offset:3px}
.sqt-related p{font-size:.9rem;line-height:1.6;margin:.6rem 0 0;color:#4b584f}
.sqt-related time{display:block;font-size:.8rem;line-height:1.4;margin-top:.6rem;color:#4b584f}
.sqt-related[data-layout="scroll"] .sqt-related-items{display:flex;overflow-x:auto;scroll-snap-type:x proximity;padding:.3rem .3rem 1rem}
.sqt-related[data-layout="scroll"] .sqt-related-card{flex:0 0 min(85%,290px);scroll-snap-align:start}
.sqt-related[data-layout="list"] .sqt-related-items{grid-template-columns:1fr}
.sqt-related[data-layout="list"] .sqt-related-card{flex-direction:row;align-items:start}
.sqt-related[data-layout="list"] img{width:28%;max-width:160px;flex-shrink:0}
@media(max-width:480px){.sqt-related[data-layout="list"] .sqt-related-card{flex-direction:column}.sqt-related[data-layout="list"] img{width:100%;max-width:none}}
</style>
<script>
(function(){
var config={"blogPath":"/blog","count":3,"layout":"grid","match":"both","fallback":"hide","thumbnails":true,"excerpts":true,"dates":false,"card":"bordered","color":"#234c3c","heading":"Related posts"};
var key='sqt-related-v2:'+config.blogPath;
if(window[key]) return;
window[key]=true;
var cache=null, pending=null, currentBody=null, currentPath='', generation=0, timer;
function pathOf(value){
try {var u=new URL(value,location.origin);if(u.origin!==location.origin||u.username||u.password)return '';return decodeURIComponent(u.pathname).replace(/\/+$/,'');}catch(e){return '';}
}
function labels(value){return Array.isArray(value)?Array.from(new Set(value.filter(function(t){return typeof t==='string';}).map(function(t){return t.trim().toLowerCase();}).filter(Boolean))):[];}
function score(post,current){
var total=0;
['tags','categories'].forEach(function(field){if(config.match!=='both'&&config.match!==field)return;var mine=labels(current[field]);labels(post[field]).forEach(function(tag){if(mine.indexOf(tag)!==-1)total++;});});
return total;
}
function plain(value){var doc=new DOMParser().parseFromString(String(value||''),'text/html');doc.querySelectorAll('script,style,iframe,object').forEach(function(n){n.remove();});return (doc.body.textContent||'').replace(/\s+/g,' ').trim().slice(0,180);}
async function read(url){
var controller=new AbortController(), timeout=setTimeout(function(){controller.abort();},8000);
try{var r=await fetch(url,{signal:controller.signal,credentials:'same-origin',redirect:'error',headers:{Accept:'application/json'}});if(!r.ok)throw Error('Feed unavailable');return await r.json();}finally{clearTimeout(timeout);}
}
async function load(){
if(cache&&Date.now()-cache.time<60000)return cache.items;
if(pending)return pending;
pending=(async function(){
var next=new URL(config.blogPath,location.origin);next.searchParams.set('format','json');
var items=[],seenUrls=new Set(),seenPosts=new Set(),pages=0;
while(next){
if(pages>=10||seenUrls.has(next.href))throw Error('Feed pagination limit or loop');
seenUrls.add(next.href);pages++;
var data=await read(next.href);if(!Array.isArray(data.items))throw Error('Unexpected feed format');
data.items.forEach(function(p){if(!p||typeof p!=='object')return;var path=pathOf(p.fullUrl);if(!path||!path.startsWith(config.blogPath+'/')||seenPosts.has(path))return;seenPosts.add(path);items.push(Object.assign({},p,{path:path}));});
if(items.length>300)throw Error('Collection exceeds 300 posts');
var page=data.pagination;
if(page&&page.nextPage){
if(typeof page.nextPageUrl!=='string')throw Error('Missing next page URL');
var candidate=new URL(page.nextPageUrl,next.href);
if(candidate.origin!==location.origin||pathOf(candidate.href)!==config.blogPath||candidate.username||candidate.password)throw Error('Invalid next page URL');
candidate.searchParams.set('format','json');next=candidate;
}else{next=null;}
}
cache={time:Date.now(),items:items};return items;
})();
try{return await pending;}finally{pending=null;}
}
function element(tag,cls,text){var n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=text;return n;}
function render(posts,isFallback,body){
var root=element('section','sqt-related');root.dataset.sqtBlog=config.blogPath;root.dataset.layout=config.layout;root.setAttribute('aria-label',isFallback?'More from the blog':config.heading);
root.append(element('h2','',isFallback?'More from the blog':config.heading));
var grid=element('div','sqt-related-items');root.append(grid);
posts.forEach(function(p){
var a=element('a','sqt-related-card');a.href=p.path;
if(config.thumbnails&&typeof p.assetUrl==='string'){
try{var src=new URL(p.assetUrl,location.origin);if(src.protocol==='https:'&&!src.username&&!src.password){var img=element('img','');src.searchParams.set('format','500w');img.src=src.href;img.alt='';img.loading='lazy';img.width=500;img.height=313;img.addEventListener('error',function(){img.remove();},{once:true});a.append(img);}}catch(e){}
}
var content=element('div','sqt-related-body');content.append(element('h3','',typeof p.title==='string'?p.title:'Untitled post'));
if(config.excerpts){var excerpt=plain(p.excerpt||p.body);if(excerpt)content.append(element('p','',excerpt));}
if(config.dates&&p.publishOn){var date=new Date(p.publishOn);if(Number.isFinite(date.getTime())){var time=element('time','',date.toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'}));time.dateTime=date.toISOString();content.append(time);}}
a.append(content);grid.append(a);
});
body.after(root);
}
async function run(){
var path=pathOf(location.href),body=document.querySelector('.blog-item-wrapper .blog-item-content');
if(path===currentPath&&body===currentBody)return;
currentPath=path;currentBody=body;generation++;var id=generation;
document.querySelectorAll('.sqt-related').forEach(function(n){if(n.dataset.sqtBlog===config.blogPath)n.remove();});
if(!body||!path.startsWith(config.blogPath+'/')||path.startsWith(config.blogPath+'/tag/')||path.startsWith(config.blogPath+'/category/'))return;
try{
var posts=await load();if(id!==generation||!body.isConnected||pathOf(location.href)!==path)return;
var current=posts.find(function(p){return p.path===path;});if(!current)throw Error('Current post missing from complete feed');
var candidates=posts.filter(function(p){return p.path!==path;}).map(function(p){return {post:p,score:score(p,current)};});
function order(a,b){return b.score-a.score||(Number(b.post.publishOn)||0)-(Number(a.post.publishOn)||0)||a.post.path.localeCompare(b.post.path);}
var matches=candidates.filter(function(p){return p.score>0;}).sort(order),fallback=false;
if(!matches.length&&config.fallback==='recent'){matches=candidates.sort(order);fallback=true;}
if(!matches.length)return;
render(matches.slice(0,config.count).map(function(p){return p.post;}),fallback,body);
}catch(e){console.warn('Squarespace Tools: related posts hidden. '+(e.message||'Collection could not be read.'));}
}
function schedule(){clearTimeout(timer);timer=setTimeout(run,100);}
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',run,{once:true});else run();
new MutationObserver(schedule).observe(document.body,{childList:true,subtree:true});
window.addEventListener('popstate',schedule);
})();
</script>Updated exports do not replace code already installed on a site. Copy and reinstall this version to receive the correction.
Check the path, shared labels, and Code Injection access. A missing article, failed request, unexpected feed format, or a collection exceeding the limits keeps the section hidden. Your original blog stays usable. Check the browser console for the Squarespace Tools message. Sites that need guaranteed support for larger libraries should use a native curated Summary Block or a maintained plugin.
Squarespace's related-post instructions · JSON compatibility notice