Notes on customizing Blogger Themes (Templates) by using widget tags directly in theme HTML
- Blogger Contempo Light Theme: Light/Dark Mode Customization Prototype; Blogger Onboarding Toast Gadget, Oct. 2025
- Fixing Oversized Blockquote Text in Blogger’s Contempo Light Theme - ChatGPT assisted, Oct. 2025
- Free/Low-cost LMS (Education app) for small NGOs: Blogger Templates vs WordPress Plugins vs Moodle, Dec. 2025
What is a Blogger Theme OR Template
- In the context of Google's Blogger (Blogspot) platform, a template and a theme are essentially the same thing. They both refer to the single XML file that defines your blog's entire design, layout, and functionality.
- Google officially rebranded "Templates" to "Themes" several years ago within the Blogger dashboard. However, third-party developers and long-time users still frequently use the term "Blogger Template"
- Unlike other platforms (like WordPress) where a theme is a collection of many files, a Blogger theme/template is a single XML file. This file contains all the HTML, CSS, and specific Blogger XML tags needed to render your site.
- You can find both "Default Themes" provided by Google and "Custom Templates" (or themes) created by third parties that you can upload as an XML file.
Notes
- Although a Blogger theme file is technically an XML document and must be well-formed, Blogger theme customization does not involve general-purpose XML programming. The XML structure mainly serves as a container and validation mechanism for HTML markup and Blogger’s proprietary widget tags. As a result, most customization challenges arise not from XML itself, but from understanding the available widget tags, their associated data objects, and their rendering behavior.
There are two very different kinds of “theme customization” in Blogger:
1. Dashboard-level customization (well supported)
This includes:
-
Adding gadgets via Layout → Add a Gadget
-
Using HTML/JavaScript gadgets
-
Adding Custom CSS via the Theme → Customize UI
-
Minor HTML insertion through gadget content
These are:
-
Relatively easy to understand
-
Well-contained
-
Mostly independent of Blogger’s internal template engine
-
Adequately documented (or self-explanatory)
✔️ You are right that this is not the problematic area.
2. Theme-level (Template-level) customization (poorly documented)
This includes:
-
Editing the theme HTML directly
-
Working with:
-
<b:widget> -
<b:includable> -
<b:include> -
<b:loop> -
data:*objects
-
-
Understanding:
-
Which widget types get which data
-
How Blogger injects server-side data
-
What defaultmarkups do
-
Rendering order and scope
-
This is where:
-
Documentation becomes thin
-
Concepts are implicit
-
Reverse engineering is required
✔️ This is exactly the area you are describing — and correctly so.
What “Declarative templating, not executable server logic” means in Blogger
When working with Blogger theme HTML, it is important to understand that Blogger’s widget tags (<b:if>, <b:loop>, <b:include>, <b:widget>, etc.) do not represent a general-purpose programming language running on the server.
Instead, Blogger uses a declarative templating system.
Declarative vs executable logic
-
Executable server logic (e.g., PHP, Node.js, Python, JSP):
-
You write instructions that explicitly control program flow.
-
You can define functions, variables, loops, and complex logic.
-
The code executes step-by-step on the server.
-
You can create arbitrary data structures and manipulate them freely.
-
-
Declarative templating (Blogger widget tags):
-
You describe what should be rendered, not how to compute it.
-
You cannot define functions, variables, or custom logic.
-
You cannot fetch data or transform it arbitrarily.
-
Blogger injects predefined data objects (
data:*) and evaluates simple conditions and loops over them. -
The system decides when and how the theme/template is evaluated.
-
In other words, Blogger themes (templates) declare rendering rules, and Blogger’s internal engine performs the actual execution.
Practical implications in Blogger themes
Because Blogger theme code is declarative:
-
You can:
-
Conditionally render markup using
<b:if> -
Iterate over provided collections using
<b:loop> -
Include reusable markup blocks via
<b:include> -
Access predefined data such as
data:posts,data:blog,data:widget, etc.
-
-
You cannot:
-
Define your own functions or reusable logic beyond
<b:includable> -
Create or mutate variables
-
Perform computations beyond simple condition checks
-
Control execution order beyond what the theme/template structure allows
-
Discover available data programmatically (you must already know what exists)
-
This explains why understanding a theme often requires knowing Blogger’s implicit data model, rather than reading explicit logic in the code.
Why this makes reverse-engineering Blogger themes difficult
Since the logic is not explicit:
-
Much of the behavior is implicit and undocumented
-
Data appears “magically” via
data:*objects -
Widget behavior depends on widget type, not code visible in the theme
-
Features like
defaultmarkupswork behind the scenes without clear public documentation
As a result, reading a Blogger theme often feels like examining the output specification of a system whose internal logic is hidden.
Big picture first
This snippet defines how the “Pages” widget is rendered in a Blogger theme.
Key points up front:
This code runs on Blogger’s servers, not in the browser
Blogger injects widget data into predefined
data:*objects<b:...>tags are Blogger widget tag (template) directives, not HTML and not JavaScriptThe output of this code is plain HTML, sent to the browser
No AJAX. No jQuery. No feeds.
1. <b:widget> — defining a widget instance
<b:widget id='PageList1' locked='false' title='Pages' type='PageList'>
This declares a widget of type PageList.
Meaning:
type='PageList'
→ This is the built-in Blogger “Pages” widget (static pages navigation)id='PageList1'
→ Unique widget instance IDlocked='false'
→ User can remove or move it in Layouttitle='Pages'
→ Default widget title
At this point, no rendering logic yet—just widget metadata.
2. <b:includable id='main'> — defining the render template
<b:includable id='main'>
An includable is a reusable rendering block.
Think of it as:
“When Blogger renders this widget, it renders the widget’s default includable template named main.”
Key idea:
Widgets can have multiple includables
Blogger calls
mainby defaultOther includables (e.g.
toggle,quickedit) may be shared across widgets
This is not a function call—it’s a server-rendered template fragment.
3. <b:if> — conditional rendering (server-side)
<b:if cond='data:title != ""'>
This checks whether the widget has a title.
data:titleis injected by BloggerIf the title is not empty, render:
<h2><data:title/></h2>
<data:title/> outputs escaped text.
Again: this happens before HTML reaches the browser.
4. data:* objects — injected widget data
Inside this widget, Blogger provides:
data:title→ widget titledata:links→ list of pagesdata:mobile→ true/falsedata:widget.instanceId→ unique widget instance ID
These are documented data objects, not arbitrary variables.
You are not fetching anything here—Blogger already fetched it.
5. <b:if cond='data:mobile'> — mobile vs desktop rendering
This is important:
<b:if cond='data:mobile'>
Blogger detects mobile context server-side and renders different HTML.
Mobile version:
Renders a
<select>dropdownUseful for small screens
Desktop version:
Renders a
<ul>listClassic navigation menu
Same data, different markup.
6. <b:loop> — iterating over injected data
<b:loop values='data:links' var='link'>
This loops over all pages.
For each link object, Blogger provides:
data:link.href→ page URLdata:link.title→ page titledata:link.isCurrentPage→ boolean
This is not JavaScript iteration.
It is server-side template iteration.
The browser never sees the loop—only the final HTML.
7. <b:if cond='data:link.isCurrentPage'> — current page styling
This logic:
Adds
class="selected"if the page is currentMarks the correct
<option>asselectedin mobile view
This is how Blogger highlights the active page without JS.
8. <b:include name='quickedit'/>
This inserts Blogger’s inline editing controls (wrench icon).
Visible only to logged-in admins
Ignored for regular visitors
This is a system-provided includable, not defined here.
9. What this code is not doing
This snippet does not:
Use jQuery
Call feeds
Fetch JSON
Manipulate DOM dynamically
Avoid page reloads
All logic is resolved before the page is delivered.
Mental model you should keep
Think of Blogger themes (templates) as:
A declarative server-side HTML generator, not an application framework.
Comments
Post a Comment