Dida
Looking for a sitemap with both filter or search functionality? Why not have both? Browse all posts from your blog in one place. You can filter by category or search by keyword to narrow down the results. New content is automatically added to the top of the list.
Step 1 — Create a New Page
- Log in to your Blogger Dashboard.
- Go to Pages in the left sidebar.
- Click + NEW PAGE.
- Give the page a title (e.g., "Sitemap" or "Archive").
Step 2 — Switch to HTML View
- In the page editor, click the Pencil icon (or "Compose view") in the top left corner.
- Select HTML view.
- Delete any existing code in the editor and paste the entire code (HTML, Script, and Style).
<div class="sm-topbar">
<div class="sm-filters">
<select id="sort">
<option value="published">Latest Posts</option>
<option value="updated">Latest Updated</option>
</select>
<select id="category">
<option value="">All</option>
</select>
</div>
<div class="sm-search-wrapper">
<input class="sm-search" id="search" placeholder="Search posts..." type="search"/>
<div class="sm-search-icon">
<svg viewBox="0 0 512 512"><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" fill="currentColor"/></svg>
</div>
</div>
</div>
<div class="sm-count" id="count">Loading...</div>
<div class="sm-posts" id="posts"></div>
<script>//<![CDATA[
const blogURL = "https://YOURBLOGNAME.blogspot.com";
const maxLabels = 20;
const postsPerLoad = 150;
let nextPage = 1;
let currentLabel = "";
let currentSort = "published";
let searchQuery = "";
async function loadLabels() {
const res = await fetch(blogURL + "/feeds/posts/default?alt=json&max-results=0");
const data = await res.json();
let labels = data.feed.category?.map(c => c.term) || [];
labels = labels.slice(0, maxLabels);
const select = document.getElementById("category");
labels.forEach(label => {
const opt = document.createElement("option");
opt.value = label;
opt.textContent = label;
select.appendChild(opt);
});
}
async function loadPosts(reset = false) {
let url = blogURL + "/feeds/posts/default";
if (currentLabel) url += "/-/" + currentLabel;
url += `?alt=json&max-results=${postsPerLoad}&start-index=${(nextPage - 1) * postsPerLoad + 1}`;
if (currentSort === "updated") {
url += "&orderby=updated";
}
const res = await fetch(url);
const data = await res.json();
const container = document.getElementById("posts");
if (reset) container.innerHTML = "";
let entries = data.feed.entry || [];
if (searchQuery) {
const query = searchQuery.toLowerCase();
entries = entries.filter(e => {
const title = e.title.$t.toLowerCase();
const labels = e.category ? e.category.map(cat => cat.term.toLowerCase()) : [];
const content = e.content ? e.content.$t.toLowerCase() : "";
const summary = e.summary ? e.summary.$t.toLowerCase() : "";
return title.includes(query) ||
labels.some(l => l.includes(query)) ||
content.includes(query) ||
summary.includes(query);
});
}
document.getElementById("count").innerText =
`${entries.length} posts found`;
entries.forEach(entry => {
const link = entry.link.find(l => l.rel === "alternate").href;
let thumb = "";
if (entry.media$thumbnail) {
thumb = entry.media$thumbnail.url;
} else if (entry.content && entry.content.$t.includes("<img")) {
const srcMatch = entry.content.$t.match(/src=["']([^"']+)["']/);
thumb = srcMatch ? srcMatch[1] : "";
}
if (thumb !== "") {
thumb = thumb.replace(/\/s[0-9]+(-c)?\//, "/s1600/");
} else {
thumb = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxYv-Ua7D6ImswxKjjbUDpy8JcZ6qZKuCrIA&s";
}
let snippet = "";
if (entry.summary) {
snippet = entry.summary.$t;
} else if (entry.content) {
snippet = entry.content.$t.replace(/<[^>]*>?/gm, '');
}
snippet = snippet.substring(0, 250) + "...";
const date = new Date(entry.published.$t).toLocaleDateString();
const div = document.createElement("div");
div.className = "sm-post";
div.innerHTML = `
<img alt="${entry.title.$t}" class="sm-thumb" src="${thumb}">
<div class="sm-info">
<div class="sm-title"><a aria-label="${entry.title.$t}" href="${link}" target="_self">${entry.title.$t}</a></div>
<div class="sm-snippet" style="font-size: 13px; color: #666; margin-bottom: 4px;">${snippet}</div>
<div class="sm-date">${date}</div>
</div>
`;
container.appendChild(div);
});
nextPage++;
}
document.getElementById("sort").onchange = function() {
currentSort = this.value;
nextPage = 1;
loadPosts(true);
};
document.getElementById("category").onchange = function() {
currentLabel = this.value;
nextPage = 1;
loadPosts(true);
};
document.getElementById("search").oninput = function() {
searchQuery = this.value;
nextPage = 1;
loadPosts(true);
};
document.getElementById("posts").addEventListener("scroll", function() {
const el = this;
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
loadPosts();
}
});
loadLabels();
loadPosts(true);
//]]></script>
<style>
:root{--sm-bg: #ffffff; --sm-text: #1e293b; --sm-card: #e8e8e8; --sm-accent: #4f46e5; --sm-border: #ccc;}
body.dark-mode{--sm-bg: #0f0f0f; --sm-text: #eee; --sm-card: #1a1a1a; --sm-accent: #818cf8; --sm-border: #282828;}
.sm-topbar{display: flex;gap: 10px;flex-wrap: wrap;}
.sm-topbar select,.sm-topbar input{padding: 8px;border-radius: 6px;border: 1px solid var(--sm-border);background: var(--sm-card);color: var(--sm-text);}
.sm-search{flex: 1;}
@media (max-width: 768px){.sm-topbar{flex-direction: column;}
.sm-filters{display: flex;gap: 10px;}
.sm-search{width: 100%;}
.sm-search-wrapper{width: 100%;}
;}
@media (max-width: 650px){.sm-snippet{display:none!important;}
.sm-title a{display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;overflow: hidden;text-overflow: ellipsis;line-height: 1.4;}
;}
.sm-count{padding: 10px;font-size: 14px;opacity: 0.8;}
.sm-posts{overflow-y: auto;}
.sm-post{display: flex;gap: 12px;margin-bottom: 10px;border-radius: 10px;}
.sm-thumb{width: 120px;height: 70px;flex-shrink: 0;border-radius: 6px;object-fit: cover;}
.sm-info{flex: 1;}
.sm-title{font-weight: bold;margin-bottom: 5px;}
.sm-date{font-size: 12px;opacity: 0.7;color: var(--sm-text);}
.sm-snippet{display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;overflow: hidden;text-overflow: ellipsis;line-height: 1.4;margin: 5px 0;}
.sm-search-wrapper{position: relative; flex: 1; display: flex; align-items: center;}
.sm-search{width: 100%; padding-right: 35px !important;}
.sm-search-icon{position: absolute; right: 10px; width: 16px; height: 16px; color: var(--sm-text); opacity: 0.5; pointer-events: none; display: flex; align-items: center; justify-content: center;}
.sm-search-icon svg{width: 100%; height: 100%;}
.sm-search:focus + .sm-search-icon{opacity: 1; color: var(--sm-accent);}
.sm-search-icon{transition: all 0.2s ease;}
</style>
Step 3 — Save and Publish
- Click Publish (or "Update" if you already saved it).
- Check the live page to ensure the posts are loading.
What You Must Change
For the sitemap to work with your specific blog, you need to modify a few lines in the <script> section.
1. The Blog URL (Mandatory)
Find this line at the very beginning of the script:
const blogURL = "https://YOURBLOGNAME.blogspot.com";
https://YOURBLOGNAME.blogspot.com with your actual blog address (e.g., https://omniotakuu.blogspot.com). Do not add a trailing slash (/) at the end.2. Maximum Labels (Optional)
Find this line:
const maxLabels = 20;
3. Posts Per Load (Optional)
const postsPerLoad = 150;
20 for faster loading.4. Thumbnail Behavior (Optional)
You can change fallback image here:
thumb = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTxYv-Ua7D6ImswxKjjbUDpy8JcZ6qZKuCrIA&s";
5. Styling (Optional Customization)
You can customize colors in this section:
:root{
--sm-bg: #ffffff;
--sm-text: #1e293b;
--sm-card: #e8e8e8;
--sm-accent: #4f46e5;
}
body.dark-mode{
--sm-bg: #0f0f0f;
--sm-text: #eee;
}
Understanding the Features
- Real-Time Search: The search bar filters titles, labels, and post content locally from the fetched results.
- Infinite Scroll: As you scroll down the
sm-postscontainer, it automatically triggers a request for the next "page" of posts. - Thumbnail Fallback: If a post doesn't have a "Featured Image," the script will automatically search the post body for the first
<img>tag. If no image is found, it uses a default placeholder. - Dark Mode Ready: The CSS uses CSS Variables (
:root). If your main blog theme uses a.dark-mode/.darkclass on the<body>, the sitemap will automatically switch colors to match. - Mobile Friendly: This sitemap is fully responsive, hidden long snippets on small screens, and optimized titles for readability.
Result
Your sitemap will now:
- Show all posts dynamically
- Allow filtering by category
- Support keyword search
- Load more posts on scroll
- Stay updated automatically
Tips
- Add this page to your navigation menu
- Name it:
- “Sitemap”
- “All Posts”
- “Browse”
And that’s it! Adding this Advanced Searchable Sitemap to your Blogger site is a great way to improve content discovery, user engagement, and site navigation. Now your readers can find exactly what they are looking for in seconds, whether they are searching by keyword or filtering through your categories.