Finding and fixing broken links with Reporting (for mere mortals)

Not long ago, there was a back-end change to our wiki instance, and our URL changed. I had a problem with that. More accurately, hundreds of little problems: broken hard links that went to the old URL!

Dynamic links update themselves, and we love them for it. I needed to find and convert hard links to dynamic ones when possible, and find and fix the ones that couldn’t be converted.

A further challenge: as a lowly, humble space admin, I didn’t have access to Confluence Storage Format or Confluence Source Editor (add-on), and I couldn’t make sweeping changes across the database. So I worked with what I had, which was the Reporting add-on.

Broken links list, part I

I modified ServiceRocket’s Reporting examples to create a list of pages that contained external links that included the old URL. My first effort looked like this:


(Limited to 3 results for illustration purposes.) Here is the markup:

{report-table:depth=all|maxResults=3} {report-header}Pages with outgoing links to XYZ.DOMAIN.COM{report-header} {expanding-reporter:content:outgoing links|as=Outlink} {content-reporter:types=page} {content-reporter} {boolean-filter:link:is external|required=true|value=true}{text-filter:link:url|exclude=.*DEF.DOMAIN.COM.*|include=.*XYZ.DOMAIN.COM.*} {date-sort:content:modification date|order=descending}{expanding-reporter} {report-column:summaryType=count|title=Page}{report-info:expanded:item|link=true}{report-column} {report-column:summaryType=count|title=Number of all outgoing links}{report-info:expanded:item>content:outgoing links>collection:size}{report-column} {report-column:title=Last updated}{report-info:expanded:item > page:modification date|format=yyyy MMM dd}{report-column} {report-column:title=URL}{report-info::Outlink>link:url}{report-column} {report-column:title=External}{report-info:expanded:Outlink>link:is external}{report-column} {report-empty}Sorry, no results{report-empty} {report-table}

I was pretty shocked by the number of links in the list! But really, that was to be expected, given a) the maturity of the wiki space and b) users not trained in how to create dynamic links! I needed to prioritize. I didn’t have access to the usual analytics, so I settled for sorting by last modified date. This also sorted by page, so all the links on one page were together in the list.

This was a good start and I methodically started fixing broken links several at a time. After using the report for awhile, I realized I needed two more pieces of information.

Broken links list, part II

I wanted to know how many links on a page had the old URL in them, so I could prioritize fixing the pages with more broken links. And after I had to use my browser’s developer tools to find one particularly stubborn broken link that was attached to a single space character (argh!), I realized I needed the display text as well, so I’d know what to look for on the page. The Link Supplier in Reporting could supply this. With a little help from ServiceRocket support and documentation, I updated my report to look like this.


(Limited to 3 results for illustration purposes.) And here is the markup:

{report-table:depth=all|maxResults=3} {content-reporter:types=page} {date-sort:content:modification date|order=descending}{collection-filter:content:outgoing links|matchItems=any}{text-filter:link:url|include=.*XYZ.DOMAIN.COM.*}{collection-filter} {content-reporter} {report-header} Pages with broken links to XYZ.DOMAIN.COM{report-header} {report-column:summaryType=count|title=Page|width=200px} {report-info:page:title|link=true}{report-column} {report-column:summaryType=sum|summaryValue=content:outgoing links>collection:size|title=Number of all outgoing links} {report-info:content:outgoing links>collection:size}{report-variable:atlassian-macro-output-type=INLINE|name=X} {local-reporter:content:outgoing links}{text-filter:link:url|include=.*XYZ.DOMAIN.COM.*}{local-reporter} {report-variable} {report-column} {report-column:injected=true|summaryType=sum|summaryValue=variable:X>size|title=Number of outgoing links meeting the criteria} {report-info:variable:X>size}{report-column} {report-column:title=Last updated} {report-info:page:modification date|format=yyyy MMM dd}{report-column} {report-column:title=Link List} {report-list} {local-reporter:content:outgoing links}{text-filter:link:url|include=.*XYZ.DOMAIN.COM.*}{local-reporter} {report-body}*Display text:* {report-info:link:body>text:split with "/">last} *URL:*{report-info:link:url}{report-body} {report-empty}No outgoing links found{report-empty} {report-list} {report-column} {report-table}


My new report is much smarter. I know what Display text to search for, since I can’t search in the source editor, and I know by looking at the URL what changes I need to make.

Now I can sort the table by last updated, or by page title, or by number of links to the old URL, depending on how I want to prioritize. When I can use the Tracking Access add-on, I can add view count , views per day and/or last view date to this report, so I can prioritize by how recently someone has used the page. I decided to include the total number of outgoing (external) links on a page, which would hint at the page’s complexity. I could also show a page’s ancestors if I wanted to prioritize by section.

If the number of links is too overwhelming, I can limit the number of results by changing the Scope and/or Time Period parameters of the Content Reporter, or by changing the Maximum Results parameter in the Report Table. In fact I recommend users limit the number of results the first time they run the report, then increase the number of results when the report is working to their satisfaction.


Fixing the broken links is still a tedious task, but this report made it much easier and faster to zero in on problem links. I’ve shared the report internally along with instructions on how to manage the number of results. And I’ll continue to educate users on creating dynamic links. In the meantime, I’m down to fewer than 200 to fix!


Norman Cates December 13, 2022

Could you PLEASE expand on how you created a report, what Service Rocket is and how to DO all these things?

This article assumes so many bits of knowledge I have no idea where to start. 

What Macros are required? And / or what addons are required?

I am pretty new to Confluence, and landed here because I need to try to find URLs in a site we are migrating. 

Links to information is totally fine. 

Like Victor Westmann likes this
Victor Westmann July 4, 2023

I would also appreciate if I could have access to more details as this knowledge is precious.

Thank you!


Log in or Sign up to comment
AUG Leaders

Atlassian Community Events