How to Display Shepherd.js Only Once

Category: Shepherd

Shepherd.js is an awesome library for creating interactive user walktroughs / client onboarding. With Shepherd, you can create an intro tour to guide the visitor through a list of steps. Each step can trigger different optional actions. For example, the user can go back a step or go to the next step, dismiss the tour without reaching the end of it or close the tour after completion. All the hard work is done for us, and we only need to write a few lines of javaScript to set it up. A very basic example is to add the following code in your js file:

const tour = new Shepherd.Tour({
    defaultStepOptions: {
        scrollTo: true,
        cancelIcon: {
            enabled: true,
        },
        useModalOverlay: true,
    }
});

//Construct the steps
const steps = [{
        title: 'My Awesome Tour Guide : Step One',
        text: 'This step is attached to the bottom of the <code>header</code> element.',
        buttons: {
            text: 'Next',
            action: tour.next
        },
    },

    {
        title: 'My Awesome Tour Guide : Step Two',
        text: 'This step is attached to the bottom of the <code>.entry-content</code> element. If no such element is found, the step appears in the center of the screen.',
        buttons: [{
                text: 'Back',
                action: tour.back
            },
            {
                text: 'Finish',
                classes: 'shepherd-button-close',
                action: tour.hide
            }
        ]
    },

]

tour.addSteps(steps);

// Initiate the tour
tour.start();

This code will create a tour with two steps that will show on each page reload. In some cases this is fine, however, in most scenarios you would prefer to display the tour only during first user visit. Even better, it might make more sense to hide the tour only after the user dismisses the tour or finishes it. In this tutorial, I will show you how to do both.

Show Shepherd.js On First Visit Only

If you are using plain javaScript, you can achieve the required effect with localstorage. You can create a key called “shepherd-tour”, store it there, then do a check if the key exists. If it does not exist, do not initiate the tour. Here is a working example:

// Initiate the tour
if(!localStorage.getItem('shepherd-tour')) {
    tour.start();
    localStorage.setItem('shepherd-tour', 'yes');
}

Simple and tidy solution. You just need to wrap the tour initiation in an if condition that checks the user browser’s localstorage. This code will only display the tour once. The next time the user loads the page, he will not see the tour, even if he never interacted with the tour.

Show Shepherd.js Until the User Dismisses or Finishes the Tour

The solution to display Shepherd tour on first visit only might be exactly what you are looking for, however in some cases we would like to have more fexibility. For example, we might need to keep showing the tour on every page reload, until the user has interacted with the tour (finishes or dismisses the tour via the close button). For this, we will once again use localstorage. Let’s adjust the above code a bit:

// helper to check the browser's localstorage
function dismissTour(){
    if(!localStorage.getItem('shepherd-tour')) {
        localStorage.setItem('shepherd-tour', 'yes');
    }
}

// Dismiss the tour when the cancel icon is clicked. Do not show the tour on next page reload
tour.on('cancel', dismissTour);

// Initiate the tour
if(!localStorage.getItem('shepherd-tour')) {
    tour.start();
}

We also need to change the logic of the finish button in step two from our example:

// Dismiss the tour when the "Finish" button has been clicked.
{
    title: 'My Awesome Tour Guide : Step Two',
    text: 'This step is attached to the bottom of the <code>.entry-content</code> element. If no such element is found, the step appears in the center of the screen.',
    buttons: [{
            text: 'Back',
            action: tour.back
        },
        {
            text: 'Finish',
            action() {
            // Dismiss the tour when the finish button is clicked. Do not show the tour on next page reload.
                dismissTour();
                return this.hide();
            }
        }
    ]
},

Our final code:

const tour = new Shepherd.Tour({
    defaultStepOptions: {
        scrollTo: true,
        cancelIcon: {
            enabled: true,
        },
        useModalOverlay: true,
    }
});

//Construct the steps
const steps = [{
        title: 'My Awesome Tour Guide : Step One',
        text: 'This step is attached to the bottom of the <code>header</code> element.',
        buttons: [{
            text: 'Next',
            action: tour.next
        }],
    },

    {
        title: 'My Awesome Tour Guide : Step Two',
        text: 'This step is attached to the bottom of the <code>.entry-content</code> element. If no such element is found, the step appears in the center of the screen.',
        buttons: [{
                text: 'Back',
                action: tour.back
            },
            {
                text: 'Finish',
                classes: 'shepherd-button-close',
                action() {
                    // Dismiss the tour when the finish button is clicked
                    dismissTour();
                    return this.hide();
                }
            }
        ]
    },

]

tour.addSteps(steps);

function dismissTour() {
    if (!localStorage.getItem('shepherd-tour')) {
        localStorage.setItem('shepherd-tour', 'yes');
    }
}

// Dismiss the tour when the cancel icon is clicked. Do not show the tour on next page reload
tour.on('cancel', dismissTour);

// Initiate the tour
if (!localStorage.getItem('shepherd-tour')) {
    tour.start();
}

Use whatever method you find more relevant for your project. Happy coding!

Read more: