Skip to main content

Creating Custom Cloud Macros 101

Can’t find a macro you need on Confluence Cloud? Join Bobby and Jessie to learn the easiest way to create your own, using ScriptRunner.
A person ponders how they will make Confluence better

Available on-demand

If there's a macro you're craving that doesn't exist in Confluence Cloud: you're in the right place.
In this session, you'll get a walkthrough of how to create your own custom macros, using ScriptRunner.
Get a guided look at:
  • What the Custom Macro feature on ScriptRunner is and how you can use it.
  • Live scripting and a guided walk-through to build 2-3 useful macros from real customer use cases.
  • A copy of the macro scripts so you can use them on your own instance.
Watch this can't-miss session now!

Who's leading this 101?

An orange placeholder
Jessie Wang
Senior Product Marketing Manager
A photograph of Bobby Bailey, Senior Customer Success Manager at ScriptRunner
Bobby Bailey
Senior Customer Success Manager, ScriptRunner
Bobby is a Senior Customer Success Manager and a ScriptRunner extraordinaire!

Resources

Here are all the resources mentioned in the demo.
An illustration of a notepad and pencil
Documentation
Learn more about custom macros in our Documentation.
Go to Documentationarrow icon
An illustration of a book filled with scripts
Script library
Discover even more ready-to-use scripts in our script library.
Go to script libraryarrow icon

User Data: Provides the User ID and Email Address of the user selected in the parameters.

def userAccountId = parameters['User'] as String

def userDataURI = "/wiki/rest/api/user?accountId=${userAccountId}"
def userData = get(userDataURI)
                .header("Accept", "application/json")
                .asObject(Map).body

def macroOutput = ("<p><strong>Data for :  </strong>${userData.publicName}</p>"
                    + "<p><strong>User ID : </strong>${userData.accountId}</p>"
                    + "<p><strong>Email Address : </strong>${userData.email}</p>")

macroOutput =   ('<ac:structured-macro ac:name="info" ac:schema-version="1" ac:macro-id="59b88725-71ee-4e2a-903f-7860cdbac9a9"><ac:rich-text-body>'
                + macroOutput +
                '</ac:rich-text-body></ac:structured-macro>')

return macroOutput

Label Report: Outputs a table with a count of the specified labels in an instance.

def label = parameters.Label


def labelDataURI = "/wiki/rest/api/label?name=${label}"
def labelData = get(labelDataURI)
                .header("Accept", "application/json")
                .asObject(Map).body

def labelId = labelData['label']['id']

def pageDataURI = "/wiki/api/v2/labels/${labelId}/pages"

def pageData = get(pageDataURI)
                .header("Accept", "application/json")
                .asObject(Map).body

def numberOfPages = 0

def macroOutput = ('<table data-layout=\"default\" ac:local-id=\"57400373-37bd-4d1a-a65d-c1385048e5e9\"><colgroup><col style=\"\" />'
        +'</h3><table data-layout=\"default\" ac:local-id=\"57400373-37bd-4d1a-a65d-c1385048e5e9\"><colgroup><col style=\"\" />'
        + '<col style=\"\" /><col style=\"\" /></colgroup>'
        + '<tbody><tr><th><p><strong>Page Title</strong></p></th><th><p><strong>Space</strong></p></th><th><p><strong>Owner</strong></p></th></tr>')

pageData.results.each{ curPage ->

    def ownerId = curPage['ownerId'] as String
    def spaceId = curPage['spaceId']

    logger.info(ownerId)

    def spaceInfoUri = "/wiki/api/v2/spaces/${spaceId}"
    def spaceInfo = get(spaceInfoUri)
                .header("Accept", "application/json")
                .asObject(Map).body

    def userInfoUri = "/wiki/rest/api/user?accountId=${ownerId}"
    def userInfo = get(userInfoUri)
                .header("Accept", "application/json")
                .asObject(Map).body           


    macroOutput = macroOutput + '<tr>'
    macroOutput = macroOutput + ("<td><ac:link><ri:page ri:content-title='${curPage['title']}'/>${curPage['title']}</ac:link></td>"
                                +"<td>${spaceInfo['name']}</td>"
                                +"<td>${userInfo['publicName']}</td>")
    macroOutput = macroOutput + '</tr>'

    ++numberOfPages
}

macroOutput = (macroOutput + '</tbody></table>')
macroOutput = ("<p>Number of Pages: ${numberOfPages}</p>" + macroOutput)
macroOutput = ("<p>Label report for label : ${parameters.Label}</p>" + macroOutput)



return macroOutput

Page Info V2: Outputs metadata of a page (e.g. Title, Created Date, Status, Owner), with the option to specify which page the metadata comes from.

import java.text.SimpleDateFormat;
import java.text.DateFormat;

def pageOption = parameters['Page'] as String
def informationType = parameters['Information Type'] as String
def curPageId = parameters.pageId as String
def pageToReadId = ''
boolean directId = false
def macroOutput = ''

logger.info(pageOption)
logger.info(informationType)
logger.info(curPageId)

// Check for ID
if(pageOption.isNumber()){
    pageToReadId = pageOption
    directId = true
} else {
    // Check for other options
    switch(pageOption){
        case '$parent':
            def curPageUri = "/wiki/api/v2/pages/$curPageId"
            def curPageInfo = get("$curPageUri")
                .header('Content-Type', 'application/json')
                .asObject(Map).body
            
            pageToReadId = curPageInfo['parentId']
            break;
        default: 
            macroOutput = 'Page option not recognised'
            break;
    }
}

logger.info(pageToReadId)

def pageUri = "/wiki/api/v2/pages/$pageToReadId"
def pageInfo = get("$pageUri")
    .header('Content-Type', 'application/json')
    .asObject(Map).body

switch(informationType){
    case 'Title':
        macroOutput = pageInfo.title as String
        break;
    case 'Created Date':
        def date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(pageInfo.createdAt as String)
        def changed = new SimpleDateFormat("dd/MM/yyyy").format(date)
        macroOutput = changed
        break;
    case 'Status': 
        macroOutput = pageInfo['status'] as String
        break;
    case 'Owner':
        def ownerId = pageInfo['ownerId']
        def ownerUri = "/wiki/rest/api/user?accountId=${ownerId}"
        def ownerInfo = get("$ownerUri")
                .header('Content-Type', 'application/json')
                .asObject(Map).body

        macroOutput = "<ac:link><ri:user ri:account-id='${ownerInfo.accountId}'/>${ownerInfo.publicName}</ac:link>"
        break;
    default:
        macroOutput = "Information Type option not recognised"
        break;
}

return """
<p> ${macroOutput} </p>
"""