This guest blog post was written by Rona Kwestel, the head of technical communication at Axoni. She transitioned from software development to technical writing almost 20 years ago and hasn’t looked back since. Flare has been her tool of choice since first testing it out in the late aughts, and she especially likes to play with the interactive features that enhance the user experience.

An important feature of any published documentation is the ability to gather feedback from readers. Not only does it enable the writer to improve the presentation and content of the documentation, but it gives readers a direct line to the people tasked with making the product comprehensible and usable. That feedback loop empowers users and gives the writer a better understanding of what users need and how they use the product.

The Challenge

Without benefit of a web development team or a third-party add-on, it can be difficult to add a feedback mechanism to your documentation. Initially, I created my own from scratch - a button at the bottom of every page, a form that appeared upon clicking the button, and a script to capture both the form contents and the page URL and populate an email message with that information - but it required invoking the user's email client to send the message since we have no backend server. This is not only clunky, but it precludes the ability to send anonymous feedback and can also be a point of failure if the user's email client is not configured to allow it.

The Aha Moment

While viewing another company's documentation that I knew was also built using MadCap Flare, I noticed their seamless interface for sending feedback, so I sent a message hoping the writer would be willing to share with me how they set it up. Not only did I hear back right away - fellow technical writers really like to help each other! - but it opened up a whole new option I had never heard of before: the Jira Issue Collector. If you're already using Jira for issue tracking, this well-hidden feature turns Jira into the missing backend piece of the puzzle at no extra cost!

The Solution

It turns out that you can set up a Jira project with one or more issue collectors that allow both internal and external users to create tickets in that project. When users populate and submit the issue collector form that gets triggered by the click of a button, it produces a ticket in the corresponding Jira project complete with the user's message, their environment, including the URL from which they sent the feedback, and, optionally, their name and email address if they want you to respond back to them. You can then set up either Jira notifications or a Slack integration to be notified whenever a ticket is added to the project, and then use that ticket to track updates to the documentation accordingly.

It also turns out that it can be pretty tricky to set this up even when following the Jira documentation. My design was to have a Feedback button on the right side of every page, which, when clicked, would expose a set of buttons indicating the helpfulness of the content. Clicking on one of those buttons would raise the correspondingly tailored Jira form for users to submit their feedback. Here's what it looks like in action (double-click on the video to view it in full-screen mode; press Esc to exit):

notes icon

The work was done in a MadCap Flare project, but it should work in any tool where you have control over the HTML, CSS, and JavaScript.

The issue collectors described here were created in Jira Server, but word on the street indicates that no substantive changes are needed when migrating this solution to Jira Cloud.

Creating the Doc Feedback Project

In order to keep the feedback tickets separate from other tickets, we (I needed the help of a full Jira Admin) created a new Doc Feedback (DF) project in Jira. The project creates only tickets of type Task and has the typical fields of Summary, Description, and Reporter along with a few others.

Most importantly, it has the Environment field added to its Create Issue and Edit/View Issue screens for Task tickets, since this is where the user's environment will be captured when they submit feedback. This data includes the URL from which they invoked the form, which is how we know exactly which page they were viewing when they submitted the feedback.

Additionally, since I wanted to support the option of users specifying whether they found the documentation helpful, we created a Helpful? custom field with values Yes, Somewhat, and Not really, and assigned it to the Create Issue and Edit/View Issue screens for Task tickets in the DF project. This would allow us to get a quick summary of how we're doing with the documentation, though admittedly people are most likely to comment when they find the documentation unhelpful.

notes icon

The Jira issue collector has a Got Feedback? template that I opted not to use because I preferred to use my own wording and styling around those options and wanted to tailor the form with verbiage reflecting the user's selection.

Creating the Issue Collectors

Because I wanted users to first specify whether they found the content helpful so I could tailor the Jira pop-up form and set the value of the Helpful? field in the underlying JavaScript code accordingly, I needed to create 3 issue collectors - one for each value. I opened the Doc Feedback project in Jira, selected the Issue Collectors tab at the bottom of the Project Settings page (you need project-level admin privileges to do this) and clicked on Add issue collector to create the first one. Then I copy/pasted that one to create the other two, modifying the following settings in each:

Field

Value

Notes

Name

  • HelpfulDoc Feedback - Helpful
  • Somewhat HelpfulDoc Feedback - Somewhat Helpful
  • Not HelpfulDoc Feedback - Not Helpful

a name for each of the issue collectors based on its Helpful? value

Description

Documentation feedback

a general description of the issue collector

Issue Type

Task

the default issue type the project defines for creation; in our case, this is a Task

Reporter

<your_jira_user_name>

the default issue reporter when the issue is created by an external user; in our case, I specified myself

Match reporter?

Attempt to match submitter email address

this allows internal Jira users to be reflected as the reporter when they submit feedback

Collect browser info

checkbox image

this collects the environment data of the user (per their consent), including the browser type, the screen resolution, the referral header, and the URL of the page from which the feedback was collected

Trigger text

Feedback

the text that will appear on the trigger button

Trigger style

Custom

this allows creating a custom JavaScript function to control the trigger behavior

Template

Custom

this allows creating a custom form

Custom fields

<checkbox list of fields>

this includes a list of fields enabled for the Create Issue screen; as you check each one you want (the only one I checked was Description), it appears in the preview of the form below it; leave ones you don't want to include there unchecked

notes icon

I could have checked the Helpful? field to add it to the form and then would only have needed one issue collector, but it includes the option of None, which I didn't want to expose, and a single issue collector wouldn't allow me to tailor the message at the top of the form based on the user's Helpful? selection.

Message

  • Helpful: We're glad you found this page helpful, but let us know if there is more we could do to improve it. Include your name and email address if you would like us to respond to your feedback directly.
  • Somewhat Helpful: It looks like we didn't quite hit the mark here. Your detailed feedback helps us improve the documentation, so let us know what works and what doesn't. Include your name and email address if you would like us to respond to your feedback directly.
  • Not Helpful: We're sorry this page didn't answer your question. Your detailed feedback helps us improve the documentation, so let us know what we missed and how we can make it better. Include your name and email address if you would like us to respond to your feedback directly.

a message for each of the issue collectors based on the selected value of Helpful?

Generated Issue Collector Embedding Code

Once the issue collector fields are set and you click on Submit, it provides the code you'll need to add to your project. The code for each issue collector is the same except for the unique collectorId that distinguishes one from the other. You can always find the code again by going back to the Issue Collectors tab, selecting the desired issue collector, and scrolling down to the Embedding this issue collector section. You can choose between Embed in HTML and Embed in JavaScript; I initially started with HTML, but later moved it to a script to keep the master page clean.

The HTML Embedding code appears as follows (identifying IDs are replaced here with <!--relevant-comment-->):

<script type="text/javascript" src="https://jira.<!--company-->.com/s/<!--hex-->-CDN/kcgegi/813004/<!--hex-->/2.2.4.7/_/download/batch/com.atlassian.plugins.jquery:jquery/com.atlassian.plugins.jquery:jquery.js?collectorId=<!--collectorID-->"></script>

<script type="text/javascript" src="https://jira.<!--company-->.com/s/<!--hex-->-T/kcgegi/<!--hex-->/4.0.4/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=en-US&collectorId=<!--collectorID-->"></script>

If you paste the embedded URLs in the generated code into a browser, you can see what the code looks like. The first one contains the jQuery JavaScript library with some Atlassian modifications and the second one contains all the form-related code.

notes icon

Important note on these scripts:

  • The first script, which downloads a jQuery library, is not only not necessary in the context of Flare, it causes a conflict that breaks other Flare features in the output, like the display of the search results and the smooth operation of the dropdown menus in the left navigation pane. This is because Flare already loads a later version of a jQuery library and the loading of the one from Jira effectively downgrades the version. To avoid this issue, do not include the first script in your code.
  • The second script contains an & character in the URL, which is a special character in HTML but not in JavaScript, so if the script is embedded in:
    • a JavaScript file, leave the code as is:...?locale=en-US&collectorId...
    • an HTML file, replace the & character with the HTML character code &amp; to avoid build errors:...?locale=en-US&collectorId...

Creating the Feedback Button

To make the Feedback button appear on every page, I added it to the master page, which describes the page layout and components of all the pages that inherit from it. To make the button sufficiently visible to catch the reader's attention without taking up too much real estate, I styled it as a vertical tab along the right edge of the page.

Default Trigger Code

The code for the Feedback button came from initially creating an issue collector with the Trigger style set to Vertical rather than Custom. Embedding the HTML code from that version of the issue collector in the <head> tag of the master page, building the output, and viewing it in the Google Chrome Inspector showed that the invoked Jira script added the following anchor tag inside the <body> tag of the page:

<a href="#" id="atlwdg-trigger" class="atlwdg-trigger atlwdg-RIGHT">Provide feedback</a>

and applied the following CSS to the anchor tag's classes:

.atlwdg-trigger {
    position: fixed;
    background: #205081;
    padding: 5px;
    border: 2px solid white;
    border-top: none;
    font-weight: bold;
    color: white !important;
    display: block;
    white-space: nowrap;
    text-decoration: none !important;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    -webkit-box-shadow: 0 0 5px rgb(0 0 0 / 50%);
    box-shadow: 0 0 5px rgb(0 0 0 / 50%);
    border-radius: 0 0 5px 5px;
}

.atlwdg-trigger.atlwdg-RIGHT {
    left: 100%;
    top: 40%;
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: top left;
    -moz-transform: rotate(90deg);
    -moz-transform-origin: top left;
    -ms-transform: rotate(90deg);
    -ms-transform-origin: top left;
    transform: rotate(90deg);
    transform-origin: top left;
}

Customized Trigger Code

To customize the look and feel of the Feedback button, I switched the issue collector's Trigger style to Custom and added the following anchor tag inside the <body> tag of the master page:

<!-- Feedback button -->
<a href="#" id="feedback-button" class="feedback-button feedback-RIGHT">Feedback</a>
notes icon

The anchor's id of feedback-button is needed to set a click function on that element in the script, while the classes feedback-button and feedback-RIGHT are used for styling in the CSS.

Then I added the following CSS to the stylesheet using the feedback-button and feedback-RIGHT classes defined on the Feedback button:

.feedback-button,
.feedback-button:link,
.feedback-button:visited {
    position: fixed;
    background: #ff5722;
    padding: 5px;
    border: 2px solid white;
    border-top: none;
    color: white;
    display: block;
    white-space: nowrap;
    text-decoration: none;
    font-size: 0.8em;
    -webkit-box-shadow: 0 0 5px rgb(0 0 0 / 50%);
    box-shadow: 0 0 5px rgb(0 0 0 / 50%);
    border-radius: 0 0 5px 5px;
}

.feedback-button:hover {
    color: black;
    text-decoration: none;
}

.feedback-button.feedback-RIGHT {
    left: 100%;
    top: 40%;
    -webkit-transform: rotate(90deg);
    -webkit-transform-origin: top left;
    -moz-transform: rotate(90deg);
    -moz-transform-origin: top left;
    -ms-transform: rotate(90deg);
    -ms-transform-origin: top left;
    transform: rotate(90deg);
    transform-origin: top left;
}
notes icon

The :link and :visited selectors eliminate the need to add the !important qualifier on some of the attributes, and the attributes defined in the :hover selector turn off the default underline for hyperlinks and change the color instead so the user recognizes that the button is active.

Creating the Feedback Helpful Container

To create a container for the Was this page helpful? buttons that would then invoke their corresponding issue collector form, I added the following code inside the <body> tag of the master page:

<!-- Feedback helpful container -->
<div class="feedback-helpful-container">
    <p class="feedback-title">Was this page helpful?</p>
    <a href="" class="feedback-trigger" id="feedback-trigger-yes">Yes</a>
    <a href="" class="feedback-trigger" id="feedback-trigger-somewhat">Somewhat</a>
    <a href="" class="feedback-trigger" id="feedback-trigger-not-really">Not really</a>
</div>
notes icon

The buttons are again defined as anchor tags, with the common feedback-trigger class used to style the buttons generally, and the unique element ids used to target each button individually for its background color in the CSS and its click function in the script.

Then I added the following code to the stylesheet, where the :link, :visited, and :hover selectors serve the same purpose as was described for the Feedback button:

.feedback-helpful-container {
    display: none;
    position: fixed;
    top: 35%;
    right: 2.5em;
    padding: 1em;
    background-color: white;
    border: 1px solid #d0d3d5;
    border-radius: 0.8em;
    box-shadow: 0px 0px 5px rgb(0 0 0 / 50%);
}
 
.feedback-title {
    margin-bottom: 0.5em;
    white-space: nowrap;
    font-weight: bold;
}
 
.feedback-trigger,
.feedback-trigger:link,
.feedback-trigger:visited {
    color: white;
    text-decoration: none;
    text-align: center;
    margin: 0.5em;
    padding: 0.1em 0.4em;
    border-radius: .25em;
    font-size: .9em;
    white-space: nowrap;
    display: block;
    width: 11em;
}
 
.feedback-trigger:hover {
    color: black;
    text-decoration: none;
}
 
#feedback-trigger-yes {
    background: #4caf50;
}
 
#feedback-trigger-somewhat {
    background: #ffc107;
}
 
#feedback-trigger-not-really {
    background: #ff5722;
}

Creating the Feedback Collector Script

The feedback-collector.js script is where all the pieces are tied together.

  • When the page is ready, it loads all the Jira issue collector scripts and sets a click function on the feedback-button element. It also defines a triggerFunction for each unique collectorId that in turn defines a click function for the corresponding feedback-trigger button id, which invokes Jira's showCollectorDialog function and toggles off the feedback-helpful-container.
  • Any field values enabled for the Create Issue screen in the Doc Feedback project can be manually set in the fieldValues attribute. Here I set recordWebInfo and recordWebInfoConsent to 1 to default the checkbox for collecting environment data to checked (the user still has the option to uncheck it), and I set customfield_12509 (the custom field ID of the Helpful? field) to the custom value corresponding to the selected feedback-trigger button (see the Tip below for how to find these IDs).

feedback-collector.js

/* Doc Feedback via Jira Issue Collector */
 
/* When the user clicks on the Feedback button, a "Was this page helpful" container with responses is displayed. Based on the user's selection, the corresponding Jira Issue Collector form with that "Helpful" value preset is raised for the user to populate and submit. This generates a Jira ticket in the Doc Feedback project. */
 
/* Some resources:
https://confluence.atlassian.com/adminjiraserver089/using-the-issue-collector-1005346596.html
https://confluence.atlassian.com/adminjiraserver089/advanced-use-of-the-jira-issue-collector-1005346607.html
https://community.atlassian.com/t5/Confluence-questions/Issue-collector-How-do-I-always-collect-the-URL-of-the-source/qaq-p/1030542
*/
 
function loadScript(url) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    $('head').append(script);  
}
 
function loadJiraScripts() {
    /* Helpful issue collector */
    loadScript('https://jira.<!--company-->.com/s/<!--hex-->-T/kcgegi/813004/<!--hex-->/4.0.4/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=en-US&collectorId=<!--collector ID-->');
 
    /* Somewhat Helpful issue collector */
    loadScript('https://jira.<!--company-->.com/s/<!--hex-->-T/kcgegi/813004/<!--hex-->/4.0.4/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=en-US&collectorId=<!--collector ID-->');
 
    /* Not Helpful issue collector */
    loadScript('https://jira.<!--company-->.com/s/<!--hex-->-T/kcgegi/813004/<!--hex-->/4.0.4/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?locale=en-US&collectorId=<!--collector ID-->');
}
 
function toggleFeedbackHelpful() {
    $('.feedback-helpful-container').toggle(500); // toggle the feedback helpful container
}
 
window.ATL_JQ_PAGE_PROPS = {
    /* Each of these feedback form trigger functions specifies the Helpful field - customfield_12509 - according to the button the user clicks. In order for this to work, the Helpful field must be added to the Create Issue screen for the Doc Feedback project in Jira. */
 
    /* Helpful */
    'f3b701a3': {
        "triggerFunction": function(showCollectorDialog) {
            jQuery("#feedback-trigger-yes").click(function(e) {
                e.preventDefault();
                showCollectorDialog();
                toggleFeedbackHelpful();
            });
        },
        fieldValues: {
            // Default the checkbox to include environment data to checked
            recordWebInfo: '1',
            recordWebInfoConsent: ['1'],
            // Set the "Helpful?" field to "Yes"
            customfield_12509: '12523'
        }
    },
 
    /* Somewhat helpful */
    '2e8f0107': {
        "triggerFunction": function(showCollectorDialog) {
            jQuery("#feedback-trigger-somewhat").click(function(e) {
                e.preventDefault();
                showCollectorDialog();
                toggleFeedbackHelpful();
            });
        },
        fieldValues: {
            // Default the checkbox to include environment data to checked
            recordWebInfo: '1',
            recordWebInfoConsent: ['1'],
            // Set the "Helpful?" field to "Somewhat"
            customfield_12509: '12524'
        }
    },
 
    /* Not helpful */
    'db5583b4': {
        "triggerFunction": function(showCollectorDialog) {
            jQuery("#feedback-trigger-not-really").click(function(e) {
                e.preventDefault();
                showCollectorDialog();
                toggleFeedbackHelpful();
            });
        },
        fieldValues: {
            // Default the checkbox to include environment data to checked
            recordWebInfo: '1',
            recordWebInfoConsent: ['1'],
            // Set the "Helpful?" field to "Not really"
            customfield_12509: '12525'
        }
    }
};
 
$(document).ready(function() {
    /* Load all the Jira issue collector scripts */
    loadJiraScripts();
     
    /* Set a click function on the feedback button to toggle the feedback helpful container in/out each time it's clicked */
    $('#feedback-button').click(function() {
        toggleFeedbackHelpful();
    })
});
light bulb icon

How to Find a Custom Field ID

To get the ID of any custom field along with the IDs of its values, click on the Create button in that project in Jira to start creating a new ticket, then right click on that field, select Inspect to view it in the Google Chrome Inspector, and find the HTML code that looks like this:

<select class="select cf-select" name="customfield_12509" id="customfield_12509">
    <option value="-1">None</option>
    <option value="12523">Yes</option>
    <option value="12524">Somewhat</option>
    <option value="12525">Not really</option>
</select>

Here, customfield_12509 is the ID of the field, and 12523, 12524, and 12525 are the IDs of the values for that field.

Including the Script in the Master Page

The last step is to add the feedback-collector.js script to the Content/Resources/Scripts folder of the project and include it in the <head> tag of the master page.

<!-- Feedback Collector -->
<script type="text/javascript" src="../Scripts/feedback-collector.js"></script>

Integrating with Slack

Because I'm not a fan of Jira notification emails, our Jira Admin set up a Slack integration so that any time new tickets are created in the Doc Feedback project, a notice appears in a Slack channel named doc-feedback. This allows me and any other channel members to be aware of feedback without the need to manage email messages. Now we wait and hope for helpful feedback!

document feedback screesnshot