Last updated Apr 16, 2024

Use content actions to count the macros in a Confluence page

This tutorial describes how to create a Forge app that displays the number of macros in a Confluence page. The app retrieves the body of the page, counts the number of macros, then displays the result in a modal dialog. A user triggers the action from an entry in the more actions (...) menu.

The final app looks like the following:

Confluence page showing a modal dialog with macros used in this page.

Before you begin

This tutorial assumes you're already familiar with the basics of Forge development. If this is your first time using Forge, see Getting started first.

To complete this tutorial, you need the following:

  • The latest version of Forge CLI. To update your CLI version, run npm install -g @forge/cli@latest on the command line.

Set up a cloud developer site

An Atlassian cloud developer site lets you install and test your app on Confluence and Jira products set up for you. If you don't have one yet, set it up now:

  1. Go to and create a site using the email address associated with your Atlassian account.
  2. Once your site is ready, log in and complete the setup wizard.

You can install your app to multiple Atlassian sites. However, app data won't be shared between separate Atlassian sites, products, or Forge environments.

The limits on the numbers of users you can create are as follows:

  • Confluence: 5 users
  • Jira Service Management: 1 agent
  • Jira Software and Jira Work Management: 5 users

The Atlassian Marketplace doesn't currently support cross-product apps. If your app supports multiple products, you can publish two separate listings on the Marketplace, but your app won't be able to make API calls across different products and instances/installations.

Create your app

The app retrieves the body of the page, counts the number of macros, then displays the result in a modal dialog.

  1. Navigate to the directory where you want to create the app.
  2. Create your app by running:
    forge create
  3. Enter a name for the app. For example, macro-counter.
  4. Select the UI kit category, and then the Confluence product.
  5. Select the confluence-macro template from the list.
  6. Open the app directory to see the app files.

Update the manifest

To register the functionality of your app, add confluence:contentAction and function modules to the manifest. The confluence:contentAction module adds an entry to the more actions (...) menu, with the value of title. The function module contains the logic to count and display the number of macros.

  1. In the app's top-level directory, open the manifest.yml file.

  2. Replace the macro entry under modules with the following confluence:contentAction.

      - key: macro-counter
        title: Macro count
        resource: main
        render: native
          function: resolver
  3. Add the follow permissions to the end of manifest.yml

        - 'read:confluence-content.summary'

Your manifest.yml should look like the following, with your value for the app ID:

    - key: macro-counter
      resource: main
      render: native
        function: resolver
      title: Macro Count
    - key: resolver
      handler: index.handler
  - key: main
    path: src/frontend/index.jsx
  id: '<your-app-id>'
    - 'read:confluence-content.summary'

Build, deploy, and install

Build, deploy, and install the app to see it in your Confluence site.

  1. Navigate to the app's top-level directory and deploy your app by running:

    forge deploy
  2. Install your app by running:

    forge install
  3. Select your Atlassian product using the arrow keys and press the enter key.

  4. Enter the URL for your development site. For example, View a list of your active sites at Atlassian administration.

Once the successful installation message appears, your app is installed and ready to use on the specified site. You can always delete your app from the site by running the forge uninstall command.

Running the forge install command only installs your app onto the selected product. To install onto multiple products, repeat these steps again, selecting another product each time. Note that the Atlassian Marketplace does not support cross-product apps yet.

You must run forge deploy before running forge install in any of the Forge environments.

View the app

With the app installed, it's time to see the entry in the more actions (...) menu.

  1. Navigate to your Confluence Cloud site, then open a page.
  2. Select the more actions (...) menu.

You'll see the Macro Count entry from the app.

When you select the menu item you will see, the following modal.

Confluence page showing a modal dialog with the default content from the macro count template

Implement the front end

Add UI Kit components that render when a user views the app. You'll use a static value for the number of macros in the page.

  1. Start tunneling to view your local changes by running:

    forge tunnel
  2. Open the src/frontend/index.jsx file.

  3. Replace the contents of the file with:

    import React, {useEffect, useState} from 'react';
    // Import required components from UI Kit
    import ForgeReconciler, { Text, useProductContext } from '@forge/react';
    // Import required for calling resolver
    import { invoke } from '@forge/bridge';
    // You'll implement countMacros later 
    const countMacros = (data) => {
        return 10;
    const App = () => {
        const [data, setData] = useState();
        const context = useProductContext();
        const contentId = context?.extension?.content?.id;
        useEffect(() => {
                // You'll implement getContent later
                invoke('getContent', { contentId }).then(setData);
        }, [contentId]);
        const macroCount = countMacros(data);
        return (
            <Text>{`Number of macros on this page: ${macroCount}`}</Text>
            <App />
  4. Refresh a Confluence page on your site, open the more actions (...) menu, and select Macro Count.

    A modal dialog displays with:

    Number of macros on this page: 10

In the code from this step:

  • The import statement lists the components to use from the UI Kit. See UI Kit components to learn more about these components.
  • setData awaits the asynchronous getContent function to complete. This function does not yet exist.
  • See UI Kit hooks to learn more about useProductContext.
  • The countMacros function returns the number of macros in the page. At this stage, the function always returns 10.

Call the Confluence REST API

Turn the static app into a dynamic app by making an API call to Confluence to retrieve the contents of the page.

  1. In terminal, navigate to the app's top-level directory and install the runtime API package by running:
    npm install @forge/api
  2. Check the tunnel is still running. If it's not, start the tunnel again.
  3. Open the src/resolvers/index.js file.
  4. Get the contents of the page by replacing the getContent function with:
    import Resolver from '@forge/resolver';
    import { route, asUser } from '@forge/api';
    const resolver = new Resolver();
    resolver.define('getContent', async ({ payload }) => {
        const response = await asUser().requestConfluence(route`/wiki/rest/api/content/${payload.contentId}?expand=body.atlas_doc_format`);
        if (!response.ok) {
            const err = `Error while getContent with contentId ${payload.contentId}: ${response.status} ${response.statusText}`;
            throw new Error(err);
        return await response.json();
    export const handler = resolver.getDefinitions();
  5. Count the number of macros by replacing the countMacros function with:
    const countMacros = (data) => {
        if (!data || !data.body || !data.body.atlas_doc_format || !data.body.atlas_doc_format.value) {
            return 0;
        const { body: { atlas_doc_format: { value } } } = data;
        const { content: contentList } = JSON.parse(value);
        const macros = contentList.filter((content) => {
            return content.type = "extension";
        return macros.length;
  6. You need to allow your app to access your page data, click “Allow access”. This will take you to another page, click “Allow” there.
  7. Refresh the Confluence page, open the more actions (...) menu, and select Macro count. The modal dialog shows the number of macros in the page.

Edit the page to add macros (e.g. type /blog post) and select Macro count again to see the number update.

Close the tunnel and deploy the app

After confirming the app works locally, deploy the app so that it continues to work when you close the tunnel.

  1. Close your tunnel by pressing Ctrl+C.
  2. Deploy your app by running:
    forge deploy

That’s it. You've built an app that retrieves the contents of a page, counts the number of macros, then displays the result in a modal dialog.

Next steps

Check out an example app, continue to one of the other tutorials, or read through the reference pages to learn more.

Rate this page: