Engineering

How to build a changelog page people subscribe to

6 min read

A changelog page is worth building when somebody would return to it. That is a higher bar than having one, and it is the bar most fail: a page that exists, is linked from the footer, is updated in bursts, and is visited by nobody except during an incident. The decisions that separate the two are made before any of it is written, and they are mostly about where the page lives and what else is generated from the same content.

What is a changelog page?

It is the public, dated list of what changed in a product, on a URL you own. It is one of five surfaces the same entries can appear on, and the useful question is not which to pick but which one is canonical and which are generated from it.

SurfaceBest forCost
Hosted pageSearch, linking, the long recordA URL and a template
In-app widgetReaching users who never visit the pageAn embed, and restraint
Docs sectionAPI and developer audiencesKeeping it beside the reference
JSON feedCustomers building on your changesStructure you already have
RSS feedDevelopers who subscribe onceAlmost nothing

Pick one canonical source, publish once, and generate the rest. Teams that hand-maintain the page and the widget separately end up with two texts that disagree, and the disagreement is discovered by a customer.

Where should a changelog page live?

On your own domain, on a stable path, with one addressable URL per entry. The three common placements are a path on the main site, a subdomain, and a section of the documentation. A path on the main site is the default worth arguing against rather than for: it inherits the site’s authority, needs no extra certificate or DNS, and keeps the page in the same navigation as everything else.

A subdomain is the right answer when the page is served by a different system from the marketing site and you would otherwise be proxying. The cost is that it accumulates authority separately. Putting the changelog in the docs is right when the audience is developers, for the reason covered in API changelog: the reader is usually already in the reference.

What matters more than the choice is that entries are individually linkable. People cite entries in tickets, incident reviews and support replies. An entry that can only be linked to as “the changelog, scroll down” gets pasted as a screenshot, and the screenshot is what circulates.

What does a changelog page need?

Five things, and the first two are where most pages fall down. A dated entry per change, newest first. A category or label per entry so a reader can skim for the kind they care about. A permalink per entry. A subscription route. A search or filter once there are more than about fifty entries.

Everything else is optional. Screenshots help and cost maintenance. Author names build trust in some products and add noise in others. Version numbers matter to callers of an API and to almost nobody else. Keep a Changelog is a reasonable default for labels if you have no reason to invent your own, and its rule that the log is written for humans is the one to keep if you discard the rest.

Group by date rather than by release when your product ships continuously. A reader scanning for “did this change before or after our incident on the ninth” is looking for a date, and a page organised by version number makes them do arithmetic.

Should it be a page or an in-app widget?

Both, from one source. The page is where search, links and the long record live. The widget is how you reach the majority of users who will never visit the page, and it works because it appears in the product they are already using.

The widget’s failure mode is interruption. A badge that demands attention for every entry gets dismissed permanently within a week, which costs you the channel for the entry that mattered. Count unread from the last time the reader looked, seed the count silently on a first visit so nobody is greeted by a badge for a year of history, and let the reader open it rather than opening it for them.

How do you make a changelog page machine readable?

Publish the same entries as a feed. A JSON feed is the lower-friction option for anyone consuming it in code, and an RSS feed is what a developer subscribing in a reader expects. Both are cheap once entries are structured data rather than hand-written HTML, which is the real argument for keeping the canonical copy structured.

Mark the page up as well. Entries are creative works with a date and a headline, and schema.org provides the vocabulary. This is worth doing for the same reason as the permalinks: it makes the page usable by things that are not a browser, including a customer’s own release process. None of this works if the underlying entries were never structured data in the first place; changelog file formats covers what Markdown, JSON and YAML each cost as the source of truth this feed and this markup actually get generated from.

Does a changelog page help SEO?

Indirectly and slowly. Individual entries rarely rank, because they target no query anybody types. The page earns its keep through links: entries get cited in support replies, forum answers and incident write-ups, and those links accumulate on a URL you own. A page updated weekly for two years is also a credible freshness signal for the product it belongs to.

What does not work is treating entries as content marketing. An entry padded to three paragraphs for length is worse at its actual job, which is telling a reader in one sentence whether something they use changed. If you want the changelog to support search, put the effort into the permalinks, the feed and the internal links from it, and let the entries stay short. Our own changelog examples page collects pages that get this balance right.

How do people subscribe?

Give them the routes they already use: an RSS or JSON feed for developers, email for people who want the important ones, and the in-app widget for everyone who will never do either. Ask what they want to hear about rather than assuming, because a reader who wants breaking changes and receives copy tweaks unsubscribes from both.

The route worth adding last is the one that closes the loop. When an entry resolves something a specific person asked for, tell that person directly instead of hoping they read the page. In changeloop the entry publishes to the page, the feed and the widget at once, and a person whose widget feedback became the GitHub issue the pull request closed is told on that issue, with a link to the entry, and sees the entry in the widget. The mechanics are the same as any subscription; the difference is that the recipient already asked. That is the argument made at length in closing the customer feedback loop.

FAQ

Should the changelog page be on a subdomain or a path? A path on the main site by default, because it inherits the site’s authority and needs no extra infrastructure. A subdomain is justified when a different system serves the page.

How many entries should the page show at once? Enough to fill a screen and no more, with pagination after that. Loading two years of history into one document is slow and makes the newest entry harder to find.

Should old entries ever be deleted? No. They are cited from outside your site and the links break. Correct an entry in place with a note, and keep the URL alive.

Does every change need to appear on the page? Only the ones a user could notice. A page that logs internal refactors trains readers to skim, and a skimmed page fails on the day it carries something urgent.


The technical claims in this article have not been independently reviewed. If something here is wrong, tell us and we will correct it.

Related on changeloop: Changelog examples, Developer docs

changeloop
The team building a closed-loop changelog. Your users ask, your team ships, the person who asked gets told.