Confluence Macro Mapping Reference: Migrating Dynamic Content
A complete technical reference for mapping Confluence macros during migration. Learn how to audit, classify, and migrate dynamic content without silent data loss.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
A Confluence macro mapping reference is a structured document that maps every macro in your Confluence instance to its equivalent, fallback, or explicit "dropped" decision in the target platform. Without one, macros are silently dropped, converted to broken placeholders, or flattened to plain text during migration — and your team discovers the damage weeks later when someone opens a page that used to have a working Jira issue table or an expandable FAQ section.
Migrating out of Confluence rarely fails because of standard text or images. It fails because of macros. Confluence relies heavily on proprietary dynamic elements — Jira issue lists, expandable sections, page properties, third-party diagrams — that have no direct equivalent in platforms like Notion, SharePoint, or Slab. If you do not build a macro mapping reference before starting a migration, you guarantee silent data loss, broken pages, and a frustrated user base.
This guide covers how Confluence stores macros internally, how to audit your macro usage, a tiered classification system for migration difficulty, concrete mapping strategies for the most common targets, and the edge cases that break most DIY migration attempts.
The Confluence legacy editor was fully deprecated on April 1, 2026. Pages migrated from Server or Data Center land in Confluence Cloud in legacy format. Unsupported nested macros are wrapped in a Legacy Content Macro — which itself cannot be copied, pasted, or indexed by Rovo AI. If you are migrating from Confluence, audit for legacy-format pages before exporting.
What Is a Confluence Macro Mapping Reference?
A macro mapping reference is a migration artifact — a lookup table that pairs each source macro with a target-platform equivalent, a lossy conversion, or an explicit removal. It is the single most important document in any Confluence migration because macros are where Confluence stores behavior, not just content.
The key insight: a useful macro mapping reference is not an alphabetical macro list. It is a migration ruleset. The minimum useful row contains:
- Macro key — the internal storage-format name (e.g.,
toc,jira,panel,code) - Macro category — formatting, navigation, dynamic content, integration, or layout
- Usage count — how many pages use this macro across your instance
- Dependencies — permissions, attachments, app data, JQL/CQL, external auth
- Target equivalent — the closest match on the destination platform
- Fidelity level — 1:1, lossy, static snapshot, or dropped
- Migration action — automated conversion, manual rebuild, or intentional removal
Use the macro's storage-format key, not its display title (e.g., jira for the Jira Issues macro, not "Jira"). Display names vary by locale and editor version. Cloud also renames familiar macros — Page Properties becomes Content Properties, for example. (support.atlassian.com)
Without this reference, migration scripts either crash on unknown macros or silently strip them. Both outcomes waste engineering time.
How Confluence Stores Macros Internally
Before you can map macros, you need to understand how Confluence represents them. Depending on your hosting type and editor version, the Confluence REST API returns macros in one of two formats. If you are migrating an older Cloud instance or moving from Data Center, you must build parsers for both.
XHTML-Based Storage Format (Server / Data Center / Legacy Cloud)
Confluence Data Center and Server store page content in an XHTML-based storage format. The format is technically XML because it includes custom elements for macros that don't comply with the XHTML definition. Every macro uses the <ac:structured-macro> element:
<ac:structured-macro ac:name="info" ac:schema-version="1">
<ac:parameter ac:name="title">Important Note</ac:parameter>
<ac:rich-text-body>
<p>This is the content of the info panel.</p>
</ac:rich-text-body>
</ac:structured-macro>The ac:name attribute specifies the macro type, <ac:parameter> elements define parameters like title or language, and <ac:rich-text-body> contains the macro's body content.
Atlassian Document Format (Cloud / New Editor)
In the legacy editor, data is XHTML-based and stored in the XML format, which allows for complicated HTML and CSS-based layouts. The cloud editor stores data in the Atlassian Document Format (ADF). ADF represents rich text stored in Atlassian products. An ADF document is a JSON object.
In ADF, macros are represented as extension nodes:
{
"type": "extension",
"attrs": {
"extensionType": "com.atlassian.confluence.macro.core",
"extensionKey": "panel",
"parameters": {
"macroParams": {
"title": { "value": "Important Note" },
"panelType": { "value": "info" }
}
}
}
}Why this matters for migration: if you export via the REST API with expand=body.storage, you get XHTML. If you use expand=body.atlas_doc_format, you get ADF JSON. Your parsing logic depends entirely on which format you pull. Atlassian's content body conversion API supports converting between storage and ADF, which gives you a normalization path before attempting rewrites. (confluence.atlassian.com)
Do not use Regex to parse macros. Macros are frequently nested (e.g., a Code Block inside an Expand macro inside an Info Panel). Regular expressions will fail on nested XML or JSON. Use an XML parser for Storage Format and an Abstract Syntax Tree (AST) traversal for ADF.
How to Audit Every Macro in Your Instance
You cannot build a mapping reference without a complete inventory. Building parsers for macros that appear on three obsolete pages is a waste of engineering time. Confluence gives you three ways to audit macro usage.
Admin UI: Macro Usage Report
If you're using Confluence Cloud or Confluence 5.10 or later, go to ⚙ > General Configuration > Macro Usage to find out how often macros provided by particular add-ons (including bundled add-ons) are used in your site. Atlassian also lists any add-ons that have macros that are not used on any pages in current spaces.
Known limitation: the Macro Usage page only shows macros on pages the current user has view permission to. If your instance uses page-level restrictions, the admin report will undercount.
CQL API: Programmatic Search
Use the Search CQL REST API to find all pages containing a specific macro. The macro field is a first-class CQL field:
GET /wiki/rest/api/search?cql=macro='panel'+AND+space=ENGINEERING
You can search for multiple macros at once:
GET /wiki/rest/api/content/search?cql=type=page AND macro in ('jira','toc','widget')
If there are more results than can be returned in a single call, the API response includes next and prev URLs with a cursor parameter for pagination.
Run a script to iterate through the most common Atlassian macros, record the hit count for each, and prioritize your mapping reference based on volume.
SQL: Direct Database Query (Data Center Only)
For auditing purposes, Confluence administrators can find pages or spaces that contain a specific macro by querying the Confluence database directly.
SELECT c.contentid, c.contenttype, c.title, s.spacekey
FROM CONTENT c
JOIN BODYCONTENT bc ON c.contentid = bc.contentid
JOIN SPACES s ON c.spaceid = s.spaceid
WHERE c.prevver IS NULL
AND c.contenttype IN ('PAGE', 'BLOGPOST')
AND bc.body LIKE '%ac:structured-macro ac:name="jira"%';Run Data Center macro SQL on a clone or staging copy. Wildcard LIKE '%...%' scans on BODYCONTENT are expensive on large sites. Query by the macro key in storage format, not the display title, or you will miss pages. (support.atlassian.com)
Build your audit script once, run it twice. Run the audit before migration planning to build the mapping reference. Run it again right before cutover — content created between planning and execution may introduce macros you haven't mapped yet.
Classify Macros by Migration Difficulty
Not all macros are equally hard to migrate. Classify them into five tiers based on what they actually do. The critical principle: map by behavior, not by appearance. A macro that looks like a simple table might actually be a live query against Jira.
Tier 1: Static Formatting Macros (Easiest)
These macros wrap static content in a visual container. The content exists in <ac:rich-text-body>, and the macro just adds styling.
| Macro Key | What It Does | Migration Approach |
|---|---|---|
panel |
Colored box with optional title | Map to callout/admonition block |
info, note, warning, tip |
Colored info boxes | Map to callout/alert block |
code |
Syntax-highlighted code block | Map to fenced code block (preserve language identifier) |
noformat |
Preformatted text | Map to <pre> or code block |
expand |
Collapsible content section | Map to <details><summary> or toggle block |
quote |
Blockquote styling | Map to blockquote |
status |
Inline status lozenge | Flatten to styled <span> |
Migration fidelity: High. These translate cleanly to Notion callout blocks, SharePoint text web parts, Markdown admonitions, or HTML equivalents. Strip the ac:structured-macro wrapper, keep the body content.
Tier 2: Layout and Structure Macros
These macros control page layout. They carry spatial arrangement, not content semantics.
| Macro Key | What It Does | Migration Challenge |
|---|---|---|
section / column |
Multi-column layout | Target platform may not support columns |
layout |
Page layout sections | Map to grid/column system or flatten |
divider |
Horizontal rule | Trivial — map to <hr> or --- |
In SharePoint Online, on modern SharePoint pages, you cannot nest web parts. SharePoint web parts are put onto the page one after another. Most target platforms are more restrictive than Confluence for layout. Expect lossy conversions here.
Tier 3: Navigation and Content Aggregation Macros
These macros generate content dynamically based on the page tree, labels, or other page metadata. The macro itself contains no content — it is a query.
| Macro Key | What It Does | Migration Challenge |
|---|---|---|
toc |
Table of contents from headings | Rebuild from heading structure or map to target's native TOC |
children |
Lists child pages | Requires page tree reconstruction |
pagetree |
Hierarchical page navigation | Platform-specific; often no equivalent |
content-by-label |
Lists pages matching labels | Requires label/tag mapping + query system |
recently-updated |
Recent changes feed | Platform-specific; often dropped |
excerpt / excerpt-include |
Pull excerpt from another page | Flatten: fetch referenced page excerpt and inject static content |
include |
Include full page content | Flatten: fetch full referenced page body and inject |
Migration fidelity: Low to medium. These rely on Confluence's internal page graph. You either rebuild the query in the target platform or replace it with a static snapshot at migration time.
Link rewriting is mandatory for flattened macros. When you flatten a "Children Display" macro into a static list of links, the URLs still point to yourdomain.atlassian.net. Your migration pipeline must maintain a global mapping dictionary of Old_Confluence_Page_ID → New_Platform_Page_URL and run a second pass to rewrite these links before final import.
Tier 4: Integration Macros
These macros pull live data from external systems, primarily Jira.
| Macro Key | What It Does | Migration Challenge |
|---|---|---|
jira |
Embeds Jira issue or JQL-driven table | No equivalent outside Atlassian ecosystem |
jirachart |
Renders Jira charts | No equivalent outside Atlassian |
roadmap |
Jira roadmap view | No equivalent |
widget |
Embeds external content (YouTube, etc.) | Map to embed/iframe block; retest per URL |
drawio |
draw.io diagram | Export as image or link to diagram file |
gliffy |
Gliffy diagram | Export as image or SVG |
Migration fidelity: Very low for Jira macros. If you are leaving the Atlassian ecosystem, Jira macros cannot follow. The standard approach: export a static snapshot at migration time and embed it as a read-only block. The live connection is gone, but historical context is preserved.
Tier 5: Third-Party Marketplace and User Macros
These are macros installed from the Atlassian Marketplace — Mosaic tabs, Refined layouts, ScriptRunner macros, Scroll Viewport, and hundreds more — plus any user macros (Velocity templates) defined at the instance level.
Due to the flexibility that Confluence Data Center offers users, it is not always possible to smoothly migrate all content to Cloud. Content formatting app developers are continuing to work on the migration process but some types of content or layouts present more challenges. Due to the limitations of Confluence Cloud, it is not possible to place many macros inside each other.
Third-party macros are the hardest to handle because:
- Their storage format is proprietary to the app vendor
- No target platform has a native equivalent
- The macro body may be encrypted, compressed, or stored outside the page body entirely
- Some macros store data in app-specific databases, not in page content
User macros are essentially Velocity templates. You can find very little about migrating them at Atlassian. User macros cannot be created in Confluence Cloud at all. Custom macro behavior must be built as a Forge app. (support.atlassian.com)
Migration approach for user macros: Read the Velocity template source from Admin > User Macros, understand what it renders, convert the rendered output to static HTML, then map that HTML to target-platform elements. For third-party macros that store no renderable content in the page body, you may need to call the app's own API to retrieve the data.
Cross-Platform Macro Mapping Table
Here is how the most common macros map to popular migration targets. This reflects what we have seen across hundreds of migrations.
| Confluence Macro | Notion | SharePoint | Slab | GitBook |
|---|---|---|---|---|
panel / info / warning |
Callout block | Text web part (styled) | No direct equivalent (bold text) | Hint block |
code |
Code block | Code Snippet web part | Code block | Code block |
expand |
Toggle block | No native equivalent | No native equivalent | Expandable block |
toc |
Auto-generated (page outline) | No native equivalent | Auto-generated | Auto-generated |
jira |
❌ Dropped (static snapshot) | ❌ Dropped | ❌ Dropped | ❌ Dropped |
children |
Synced blocks (manual) | Page library web part | Topic listing | Page listing |
section / column |
Column layout | Section layout | ❌ Flattened | ❌ Flattened |
excerpt |
❌ Dropped (inline content) | ❌ Dropped | ❌ Dropped | ❌ Dropped |
drawio / gliffy |
Image embed (exported PNG/SVG) | Image web part | Image embed | Image embed |
status |
Inline mention or emoji | ❌ Dropped | ❌ Dropped | ❌ Dropped |
page-properties |
Database properties | List metadata columns | ❌ Dropped | ❌ Dropped |
Each macro family in your wiki needs a conversion rule for the target platform, tested against real content.
For the SharePoint direction specifically, see Confluence to SharePoint Migration: Methods, Limits & Macro Mapping.
Handling Specific High-Complexity Macros
Some macros deserve individual attention because of their technical complexity during extraction.
Draw.io and Gliffy Diagrams
Confluence does not store the visual representation of a diagram in the page body. It stores a macro reference pointing to a hidden attachment. Your pipeline must:
- Parse the page body to detect the
drawioorgliffymacro. - Extract the attachment name or ID from the macro parameters.
- Query the
/wiki/rest/api/content/{pageId}/child/attachmentendpoint. - Download the
.png,.svg, or source file. - Upload the file to the target platform.
- Replace the macro in the parsed page body with a standard image tag (
<img>or! []()) pointing to the new file URL.
Jira Issue Macro
When migrating to a platform without a native Jira integration, Jira macro data disappears. Flatten it to a static HTML table:
- Extract the
serverandjql(orissue-key) parameters from the macro. - Authenticate against the Jira REST API.
- Execute the JQL query to retrieve ticket data (Summary, Status, Assignee).
- Generate an HTML table containing this data.
- Replace the macro node with the static table.
The data no longer updates in real time, but historical context is preserved. A stronger approach: preserve the JQL query as metadata alongside the snapshot so teams can reconnect it later if the target gains Jira integration.
Page Properties and Content Properties Report
The page-properties and page-properties-report macros form a makeshift relational database within Confluence. Users define key-value pairs inside a Page Properties macro, and a Report macro on a parent page aggregates them using a specific label. In Cloud, these are renamed to Content Properties and Content Properties Report. The report caps results at 30 per page. (support.atlassian.com)
Migrating this requires multi-stage compilation:
- Phase 1 (Export): Identify all pages with the
page-propertiesmacro. Extract the data table and store it in your migration database, indexed by labels. - Phase 2 (Translation): Convert each
page-propertiesmacro into a standard HTML table so data remains visible on individual pages. - Phase 3 (Aggregation): When processing a page with
page-properties-report, read the label from macro parameters. Query your migration database for all tables with that label. Construct a master HTML table and inject it.
This is one of the most expensive operations in a Confluence migration — it requires full workspace indexing before a single page can be accurately transformed.
Handling Nested Macros
Nested macros are the single biggest source of migration failures. A Panel inside a Column inside a Section is common in Data Center — but most target platforms and even Confluence Cloud's new editor cannot represent that nesting.
While nested body macros are commonly used in the Data Center version of Confluence, Atlassian does not permit their use in Confluence Cloud. The migration challenge primarily arises from differences in how text is edited and stored: On-Premise uses text edited within the macro's body which supports nested structures. Cloud macros do not contain a body; instead, text is directly edited using the cloudText attribute.
Content migrated from Server or Data Center that contains unsupported nesting lands in the Legacy Content Macro. You can only copy text out of unsupported legacy blocks, Smart Links render as plain URLs, inline comments are unavailable, and Rovo AI features ignore text inside certain blocks.
Practical strategy for nested macros:
- Identify pages with nesting depth > 1 — Parse the storage format XML and count
<ac:structured-macro>elements inside other macros'<ac:rich-text-body>elements. - Flatten from the inside out — Extract the innermost macro's body content, convert it, then work outward.
- Preserve the outermost container — If the outer macro has a visual equivalent (Panel, Section), map it. Drop pure structural wrappers.
- Log every flattening decision — Your mapping reference should record which pages had nested macros and what changed.
Handling Unknown Macros and Silent Failures
No matter how comprehensive your mapping reference is, users will have installed obscure marketplace apps or used deprecated macros. Your migration pipeline must have a fallback mechanism for unknown macros.
When your script encounters an ac:structured-macro or ADF extension not in your mapping reference:
- Log a warning with the Page ID and Macro Name.
- Attempt to extract any plain text from the macro's
rich-text-bodyorcontentarray. - Wrap the extracted text in a clearly visible HTML block (e.g.,
<div style="border: 1px solid red;">UNMAPPED MACRO: [Name]</div>) so users can manually review it post-migration.
Dropping unknown macros silently is the fastest way to lose trust during a migration.
The Legacy Editor Complication
Atlassian announced the deprecation of the legacy editor in Confluence Cloud, with full deprecation on April 2026. All editing has moved to the cloud editor.
Pages migrated from Server or Data Center land in Confluence Cloud in legacy format. This means if your source is Confluence Cloud, some pages may already be in ADF while others are in legacy XHTML. Your parsing pipeline needs to handle both formats.
A page looking fine in read mode is not validation. Legacy Content Macro wrappers preserve content, but they are compatibility mode with real feature loss. Test macro-heavy pages in the editor, in exports, and in any downstream AI or search workflow you depend on. Pull the raw storage format via the API, not the rendered page.
Common Mistakes in Macro Mapping
1. Mapping by display name instead of macro key. Display names vary by locale and editor version. Always use the storage-format key.
2. Ignoring bodyless macros. Macros like status, anchor, and jira are inline or bodyless. They will not appear in a naive scan for <ac:rich-text-body> elements. Parse <ac:structured-macro> elements directly.
3. Treating Marketplace macros as built-in. Many more macros are available from the Atlassian Marketplace. If you do not separate built-in macros from Marketplace macros in your audit, you will underestimate the complexity.
4. Skipping the permission check. In Confluence Cloud, there is no built-in option to get a complete list of every Confluence macro. The Macro Usage admin page and CQL both respect page-level permissions. A space admin may not see macros on restricted pages.
5. Not testing with real content. A macro mapping looks correct in a spreadsheet but fails on real pages. Run your conversion logic against a representative sample of 50–100 pages before committing to a full migration.
Building the Mapping Reference Document
Your macro mapping reference should be a living spreadsheet or database, not a static document. Here is the structure we use at ClonePartner across migration projects:
| Column | Description |
|---|---|
macro_key |
Storage-format name (panel, jira, toc) |
macro_source |
Built-in, Marketplace app name, or User Macro |
usage_count |
Number of pages using this macro |
spaces_affected |
Which spaces contain pages with this macro |
has_body |
Whether the macro wraps content (true / false) |
is_nested |
Whether this macro appears inside another macro |
target_equivalent |
What it maps to in the target platform |
fidelity |
1:1, lossy, snapshot, dropped |
migration_action |
auto, manual, drop, rebuild |
pilot_page |
Representative page for testing this macro |
notes |
Edge cases, parameter dependencies, test results |
Your mapping reference is your migration contract. Share it with stakeholders before writing a single line of migration code. Every "dropped" macro in the reference is a feature your users will lose. Get explicit sign-off on those losses before cutover, not after.
Building the Migration Pipeline
Writing the mapping reference is the first step. Executing it requires a middleware pipeline:
- Extraction Layer: Polls the Confluence REST API, requesting
expand=body.storage,body.atlas_doc_format. Handles Atlassian's rate limits (typically 100 requests per minute for standard Cloud instances). - Transformation Engine: Passes raw JSON/XML through an AST parser. Matches nodes against your mapping reference. Executes secondary API calls (Jira, Attachments) as needed.
- Link Rewriter: Scans transformed output for Atlassian URLs and replaces them with target platform URLs using a pre-computed mapping index.
- Load Layer: Pushes final HTML/Markdown to the target platform's API, handling its rate limits and pagination rules.
Building this pipeline from scratch typically takes an internal engineering team 4 to 6 weeks, not including time fixing edge cases discovered during user acceptance testing.
When to Automate vs. Manually Rebuild
Automate when:
- The macro is Tier 1 or Tier 2 (formatting or layout)
- The target platform has a direct equivalent
- The macro appears on more than 50 pages
- The conversion rule is deterministic (no ambiguity)
Manually rebuild when:
- The macro is a custom User Macro with business logic
- The page is a critical runbook or SOP that must be exact
- Nested macros create ambiguous conversion paths
- The macro relies on live data (Jira, external APIs) that you want to reconnect
Drop intentionally when:
- The macro is deprecated within Confluence (e.g., legacy-editor-only macros)
- The macro has zero usage in current pages
- The rendered output has no value in the target context (e.g., Confluence-specific navigation macros on a platform with its own nav)
For a broader look at handling automations and macros during platform migrations, see Your Help Desk Data Migration's Secret Saboteur: Automations, Macros, and Workflows.
The Complete Macro Mapping Workflow
- Run the macro audit — Use the Admin Macro Usage report, supplement with CQL queries for restricted pages, and cross-reference with your Marketplace app inventory.
- Classify every macro into the five tiers above.
- Build the mapping table with target equivalents and fidelity levels.
- Get stakeholder sign-off on every "dropped" and "lossy" entry.
- Write conversion rules for each macro that maps to an automated action.
- Test on a sample space — Pick your most macro-heavy space and run the full pipeline.
- Review the output page by page against the original.
- Iterate — Adjust conversion rules based on test results.
- Execute the full migration with the finalized mapping reference.
- Post-migration audit — Compare source macro counts against target content to verify nothing was silently dropped.
Separating "Looks Similar" from "Behaves the Same"
A good Confluence macro mapping reference is not a wiki glossary. It is an execution document. Publish it before migration work starts, keep it keyed by storage-format macro name, and separate looks similar from behaves the same. That distinction is where most macro data loss happens.
When a Confluence instance is small, text-heavy, and light on apps, you can accept native replacements and move fast. When macros carry business logic, permissions, external data, or nested layouts, the right answer is a pilot, a scripted rewrite, and a validation pass before cutover.
We have built macro mapping references and executed migrations for 1,500+ projects. Our team handles the audit, builds the mapping table, writes the conversion logic, and runs the full pipeline — from ADF translation to Storage Format XML parsing to the recursive API calls required to flatten complex macros.
Frequently Asked Questions
- How do I find all macros used in my Confluence instance?
- In Confluence Cloud or Data Center 5.10+, go to ⚙ > General Configuration > Macro Usage. This report shows usage counts per macro, broken down by add-on. For restricted pages the admin can't see, supplement with CQL API queries like `macro='panel'+AND+space=ENGINEERING`. On Data Center, you can also run SQL queries against the database directly. Note that both the admin page and CQL are permission-scoped, so a low-privilege account will undercount.
- What Confluence macros are lost during migration?
- Jira integration macros (jira, jirachart, roadmap) have no equivalent outside the Atlassian ecosystem and are always dropped or flattened to static snapshots. Dynamic macros like children, recently-updated, and content-by-label lose their live query behavior. Third-party Marketplace macros and custom User Macros have no standard equivalent on any target platform. Static formatting macros like panels, code blocks, and expand sections usually convert cleanly.
- What is the difference between Confluence Storage Format and ADF?
- Storage Format is an XHTML-based XML structure used in Confluence Data Center, Server, and legacy Cloud pages. Atlassian Document Format (ADF) is a nested JSON structure used in the modern Confluence Cloud editor. When migrating, you may need to handle both formats if your source contains a mix of legacy and cloud-editor pages. The Confluence REST API returns one or the other depending on which body expansion you request.
- Can nested Confluence macros be migrated to other platforms?
- Rarely with full fidelity. Most target platforms — including SharePoint, Notion, and even Confluence Cloud's new editor — cannot represent deeply nested macro structures. The standard approach is to flatten from the inside out: extract the innermost macro's content, convert it, and work outward, preserving the outermost visual container where a target equivalent exists.
- What is the difference between a macro key and a macro display name?
- The macro key is the internal identifier used in storage format (e.g., 'jira', 'toc', 'panel'), while the display name is what users see in the editor (e.g., 'Jira Issues', 'Table of Contents', 'Panel'). Always use the macro key when building migration scripts or CQL queries. Display names vary by locale and editor version, and some macros are renamed in Cloud (e.g., Page Properties becomes Content Properties).