# Ending a Tour

> Control how a Driver.js tour ends. Ask users to confirm before they leave, stop them from exiting early, and tell a finished tour apart from one that was closed.

A tour ends when the user finishes the last step, or leaves early with the close button, the <kbd>Escape</kbd> key or a click on the overlay. The examples below show how to step in before the tour closes, and how to find out which way it ended.

## Confirm on Exit

You can use the `onDestroyStarted` hook to add a confirmation dialog or some other logic when the user tries to exit the tour. In the example below, we ask for confirmation only when the user leaves before finishing the tour.

```js
import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  showProgress: true,
  steps: [
    { element: '#confirm-destroy-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\'s walk you through it.', side: "left", align: 'start' }},
    { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: "bottom", align: 'start' }},
    { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: "bottom", align: 'start' }},
    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }
  ],
  // onDestroyStarted is called when the user tries to exit the tour
  onDestroyStarted: (element, step, { reason }) => {
    if (reason === "done" || confirm("Are you sure?")) {
      driverObj.destroy();
    }
  },
});

driverObj.drive();
```

> **Note:** By overriding the `onDestroyStarted` hook, you are responsible for calling `driverObj.destroy()` to exit the tour.

## Prevent Exit

You can also prevent the user from exiting the tour using `allowClose` option. This option is useful when you want to force the user to complete the tour before they can exit.

In the example below, you won't be able to exit the tour until you reach the last step.

```js
import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  showProgress: true,
  allowClose: false,
  steps: [
    { element: '#prevent-exit', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\'s walk you through it.', side: "left", align: 'start' }},
    { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: "bottom", align: 'start' }},
    { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: "bottom", align: 'start' }},
    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }
  ],
});

driverObj.drive();
```

## Finished or Closed

`onDestroyStarted` and `onDestroyed` receive `reason` in their options, telling you why the tour ended:

- `"done"`: the user moved past the last step
- `"close"`, `"escape"` or `"overlay"`: the user left early with the close button, the <kbd>Escape</kbd> key or a click on the overlay
- `"replaced"`: another tour or highlight started
- `"api"`: your own code called `destroy()`

Use it to mark onboarding as complete only when the user actually finished it, or to log the step where users drop off. Finish the tour below, or leave it early, to see the reason.

```js
import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  steps: [
    // ...
  ],
  onDestroyed: (element, step, { reason, index }) => {
    if (reason === "done") {
      markOnboardingComplete();
    } else {
      trackDropOff({ reason, step: index });
    }
  },
});

driverObj.drive();
```

> **Note:** A `destroy()` you call from a hook keeps the reason of the user action that started it. In the [Confirm on Exit](#confirm-on-exit) example above, `onDestroyed` gets `"close"`, not `"api"`.
