Skip to main content
Cloud icon
Cloud
ScriptRunner for Confluence logo

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
Product Marketing Manager, ScriptRunner for Confluence Cloud
Jessie is the Product Marketing Manager for ScriptRunner for Confluence Cloud.
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.

1def userAccountId = parameters['User'] as String
2
3def userDataURI = "/wiki/rest/api/user?accountId=${userAccountId}"
4def userData = get(userDataURI)
5                .header("Accept", "application/json")
6                .asObject(Map).body
7
8def macroOutput = ("<p><strong>Data for :  </strong>${userData.publicName}</p>"
9                    + "<p><strong>User ID : </strong>${userData.accountId}</p>"
10                    + "<p><strong>Email Address : </strong>${userData.email}</p>")
11
12macroOutput =   ('<ac:structured-macro ac:name="info" ac:schema-version="1" ac:macro-id="59b88725-71ee-4e2a-903f-7860cdbac9a9"><ac:rich-text-body>'
13                + macroOutput +
14                '</ac:rich-text-body></ac:structured-macro>')
15
16return macroOutput

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

1def label = parameters.Label
2
3
4def labelDataURI = "/wiki/rest/api/label?name=${label}"
5def labelData = get(labelDataURI)
6                .header("Accept", "application/json")
7                .asObject(Map).body
8
9def labelId = labelData['label']['id']
10
11def pageDataURI = "/wiki/api/v2/labels/${labelId}/pages"
12
13def pageData = get(pageDataURI)
14                .header("Accept", "application/json")
15                .asObject(Map).body
16
17def numberOfPages = 0
18
19def macroOutput = ('<table data-layout=\"default\" ac:local-id=\"57400373-37bd-4d1a-a65d-c1385048e5e9\"><colgroup><col style=\"\" />'
20        +'</h3><table data-layout=\"default\" ac:local-id=\"57400373-37bd-4d1a-a65d-c1385048e5e9\"><colgroup><col style=\"\" />'
21        + '<col style=\"\" /><col style=\"\" /></colgroup>'
22        + '<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>')
23
24pageData.results.each{ curPage ->
25
26    def ownerId = curPage['ownerId'] as String
27    def spaceId = curPage['spaceId']
28
29    logger.info(ownerId)
30
31    def spaceInfoUri = "/wiki/api/v2/spaces/${spaceId}"
32    def spaceInfo = get(spaceInfoUri)
33                .header("Accept", "application/json")
34                .asObject(Map).body
35
36    def userInfoUri = "/wiki/rest/api/user?accountId=${ownerId}"
37    def userInfo = get(userInfoUri)
38                .header("Accept", "application/json")
39                .asObject(Map).body           
40
41
42    macroOutput = macroOutput + '<tr>'
43    macroOutput = macroOutput + ("<td><ac:link><ri:page ri:content-title='${curPage['title']}'/>${curPage['title']}</ac:link></td>"
44                                +"<td>${spaceInfo['name']}</td>"
45                                +"<td>${userInfo['publicName']}</td>")
46    macroOutput = macroOutput + '</tr>'
47
48    ++numberOfPages
49}
50
51macroOutput = (macroOutput + '</tbody></table>')
52macroOutput = ("<p>Number of Pages: ${numberOfPages}</p>" + macroOutput)
53macroOutput = ("<p>Label report for label : ${parameters.Label}</p>" + macroOutput)
54
55
56
57return 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.

1import java.text.SimpleDateFormat;
2import java.text.DateFormat;
3
4def pageOption = parameters['Page'] as String
5def informationType = parameters['Information Type'] as String
6def curPageId = parameters.pageId as String
7def pageToReadId = ''
8boolean directId = false
9def macroOutput = ''
10
11logger.info(pageOption)
12logger.info(informationType)
13logger.info(curPageId)
14
15// Check for ID
16if(pageOption.isNumber()){
17    pageToReadId = pageOption
18    directId = true
19} else {
20    // Check for other options
21    switch(pageOption){
22        case '$parent':
23            def curPageUri = "/wiki/api/v2/pages/$curPageId"
24            def curPageInfo = get("$curPageUri")
25                .header('Content-Type', 'application/json')
26                .asObject(Map).body
27            
28            pageToReadId = curPageInfo['parentId']
29            break;
30        default: 
31            macroOutput = 'Page option not recognised'
32            break;
33    }
34}
35
36logger.info(pageToReadId)
37
38def pageUri = "/wiki/api/v2/pages/$pageToReadId"
39def pageInfo = get("$pageUri")
40    .header('Content-Type', 'application/json')
41    .asObject(Map).body
42
43switch(informationType){
44    case 'Title':
45        macroOutput = pageInfo.title as String
46        break;
47    case 'Created Date':
48        def date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(pageInfo.createdAt as String)
49        def changed = new SimpleDateFormat("dd/MM/yyyy").format(date)
50        macroOutput = changed
51        break;
52    case 'Status': 
53        macroOutput = pageInfo['status'] as String
54        break;
55    case 'Owner':
56        def ownerId = pageInfo['ownerId']
57        def ownerUri = "/wiki/rest/api/user?accountId=${ownerId}"
58        def ownerInfo = get("$ownerUri")
59                .header('Content-Type', 'application/json')
60                .asObject(Map).body
61
62        macroOutput = "<ac:link><ri:user ri:account-id='${ownerInfo.accountId}'/>${ownerInfo.publicName}</ac:link>"
63        break;
64    default:
65        macroOutput = "Information Type option not recognised"
66        break;
67}
68
69return """
70<p> ${macroOutput} </p>
71"""