# Pages & URL targeting

URL: https://docs.ablyft.com/guides/audiences-and-delivery/pages/

> Define on which URLs an experiment runs, when ABlyft checks them and how a page is deactivated again.



A **page** tells ABlyft **where** an experiment should run. It consists of URL rules and, if needed, a piece of JavaScript.
You create a page once and attach it to as many experiments as you like.

An experiment only runs on a visitor's current page if at least one of its attached pages matches. Without a page, an
experiment cannot be started.

## Create a page

There are two ways:

* From an experiment: in the card **Pages** ("WHERE should it run?"), click **+**. The new page is attached to the
  experiment automatically.
* From the navigation: go to **Targeting & Goals → Pages** and create a new page. Later, attach it to an experiment with
  the selection button in the **Pages** card (the window is titled "Attach pages to experiment").

The page form has these sections:

| Section       | Purpose                                                                                  |
| ------------- | ---------------------------------------------------------------------------------------- |
| **General**   | **Name** (clear and descriptive, unique in the project) and an optional **Description**. |
| **Targeting** | The URL rules, and under **Advanced Targeting** the JavaScript rules.                    |
| **Trigger**   | When ABlyft checks the targeting.                                                        |

## URL rules

In **Targeting**, add one rule per row with **Add new URL**. Each rule has three parts:

| Column    | Description                         |
| --------- | ----------------------------------- |
| **Type**  | **Include** or **Exclude**.         |
| **URL**   | The address or text to check.       |
| **Match** | How the URL is compared, see below. |

### How rules are combined

* The page matches if **at least one Include rule** matches the current URL.
* If **any Exclude rule** matches, the page does not match, no matter what the Include rules say.

> **You need at least one Include rule:** Exclude rules only remove URLs from the ones you included. A page with only Exclude rules never matches.

### Match types

| Match                              | The rule applies if …                                                                               |
| ---------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Simple (URL must match)**        | the address matches. Protocol, query string, hash and a trailing slash are ignored.                 |
| **Exact (URL + query must match)** | the complete address matches, including the query string and the hash. A trailing slash is ignored. |
| **Substring (URL contains)**       | the current URL contains your text anywhere.                                                        |
| **Regex (pattern match)**          | the current URL matches your regular expression.                                                    |

For **Simple** and **Exact**, enter a full URL such as `https://example.com/product`. The host is compared as written,
so `www.example.com` and `example.com` are different.

Examples:

| Match     | URL in the rule                   | Matches                                            | Does not match                                         |
| --------- | --------------------------------- | -------------------------------------------------- | ------------------------------------------------------ |
| Simple    | `https://example.com`             | `https://example.com/`, `https://example.com/?a=b` | `https://example.com/home`                             |
| Exact     | `https://example.com/?a=b`        | `https://example.com/?a=b`                         | `https://example.com/`, `https://example.com/?a=b&c=d` |
| Substring | `/product/`                       | `/product/shirt`, `/product/a/b`                   | `/products/overview`                                   |
| Regex     | `/news/(vips\|styles\|dresses).*` | `/news/vips`, `/news/styles/latest`                | `/news/dinners`                                        |

> **Several domains or languages:** Simple and Exact include the host. If the same experiment should run on several domains, use **Substring** or
> **Regex** with the path only (for example `/product/`). Combine this with [environments](https://docs.ablyft.com/guides/audiences-and-delivery/environments/)
> to control on which site the experiment runs.

### Target URL parameters

To target a page by its query parameters, use **Exact**, or **Substring** and **Regex** with the parameter in the text,
for example `utm_source=newsletter`. For more flexible conditions, use
[advanced targeting](#advanced-targeting-javascript-rules) and read the parameter with `ablyftTools.getUrlParameter()`:

```js
return ablyftTools.getUrlParameter('utm_source') === 'newsletter';
```

`getUrlParameter()` returns `null` if the parameter is missing. See the
[tools reference](https://docs.ablyft.com/developers/reference/javascript-api/tools/#geturlparameter). If you only want to limit who sees an
experiment and not where it runs, an [audience](https://docs.ablyft.com/guides/audiences-and-delivery/audiences/) with the criterion
**URL parameter** is easier.

## Advanced targeting: JavaScript rules

Open the section **Advanced Targeting** ("Is more to consider than URLs?") if the URL alone is not enough, for example if
the page must also contain a certain element.

In the code field **Rules**, write JavaScript that returns `true` if the page is valid. The URL rules and the JavaScript
rule must both be fulfilled.

```js
// Valid only if the page shows a product with a "sale" label
return document.querySelector('.product .label-sale') !== null;
```

The code can use `ablyftTools` and `Tools` (see [tools](https://docs.ablyft.com/developers/reference/javascript-api/tools/)) and `User`. If your code
throws an error, the rule counts as not fulfilled.

| Option                      | Description                                                                                                                                                          |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Poll on rules**           | Checks the JavaScript rule repeatedly for up to about 2 seconds instead of only once. Turn it on if the content you check appears shortly after the page has loaded. |
| **Always embed in snippet** | Includes the page in the snippet even if no running experiment uses it. This is usually not needed. Only enable it if your setup requires it.                        |

## Trigger: when ABlyft checks the page

The trigger decides **when** the targeting is checked. For most websites, leave the default. The default for new pages
is set in **Project → Settings** under **Project Activations Settings → Default Page Trigger**.

| Trigger                                                      | ABlyft checks the page …                                                                                                                                           |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Direct (immediately when ABlyft runs)**                    | once, as soon as the snippet runs. Right for classic websites.                                                                                                     |
| **URL Change (check for url changes using the history API)** | at the start and whenever the URL changes through `history.pushState`, `history.replaceState` or back/forward navigation. Preferred for most single-page apps.     |
| **URL Change (check for url changes using polling)**         | at the start and whenever the URL changes, detected by comparing the URL every 10 ms. Use it if your app changes the URL in a way the history API does not report. |
| **DOM Change (when something on the page is changing)**      | at the start and whenever elements are added, removed or changed. See [Dynamic content](https://docs.ablyft.com/developers/application-integration/dynamic-content/).                     |
| **Callback (when the callback function is called)**          | when your own code calls `activate()`.                                                                                                                             |
| **API (manual activation by an API / JavaScript call)**      | only when your website activates the page with a JavaScript call.                                                                                                  |

The URL and DOM change triggers are meant for dynamic websites and single-page apps, see
[SPA navigation](https://docs.ablyft.com/developers/application-integration/spa-navigation/).

### Callback trigger

When you choose **Callback**, a code field appears with the default `activate();`. Your code decides when to call
`activate()`. Calling `activate(false)` deactivates the page again.

```js
// Activate the page as soon as the website announces the event
document.addEventListener('video-finished', function () {
  activate();
});
```

### API trigger

When you choose **API**, the field **API trigger code** shows the code to copy. Run it on your website at the moment the
page should be activated:

```html
<script>
window['ablyft'] = window['ablyft'] || [];
window['ablyft'].push({
    eventType: 'activatePage',
    pageApiName: 'checkout-step-2'
});
</script>
```

`pageApiName` is the **API Name** of the page. It is set in the section **Advanced Settings** of the page and is filled
in from the page name. The API name must be unique in the project. For all options, see
[`activatePage`](https://docs.ablyft.com/developers/reference/javascript-api/push/#activatepage) in the JavaScript API.

## Deactivation mode

A page can be checked several times, for example after each URL change. The **Deactivation mode** (section
**Advanced Settings** of the page) defines what happens when a page that was active is checked again and no longer
fits.

| Mode                | Behavior                                                                                                                                                          |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Reset** (default) | The page is deactivated when the trigger fires but the targeting is no longer valid, and the reset code of its experiments runs.                                  |
| **Deactivate**      | Like Reset, but the reset code does not run.                                                                                                                      |
| **Force-reset**     | The page is deactivated and reset **every time** the trigger fires, and activated again if the targeting is valid. Use it to rebuild the variation on each check. |
| **Persistent**      | The page is never deactivated. It stays active.                                                                                                                   |

Calling [`deactivatePage`](https://docs.ablyft.com/developers/reference/page-api/#deactivate-a-page) from your code follows the same modes.

Reset code is the optional **Reset JS code** of an experiment or variation. It runs only if **Use SPA features** is turned on
in **Project → Settings** (**Project Activations Settings**). On classic websites with the **Direct** trigger, the deactivation
mode usually has little effect, because the page is checked only once.

## Check your page

Open the experiment in [preview](https://docs.ablyft.com/guides/experiments/preview-and-qa/) and visit the URLs that should and should not
match. If an experiment does not show, see
[Experiment not showing](https://docs.ablyft.com/guides/troubleshooting/experiment-not-showing/).

> Changes to the URL rules, the trigger, the JavaScript rules and the other page settings are published automatically.
> Visitors receive them after the [publishing delay](https://docs.ablyft.com/guides/experiments/start-pause-stop/#publishing-delay).

## Next steps

- [Audiences](https://docs.ablyft.com/guides/audiences-and-delivery/audiences/): Choose who sees an experiment.
- [Environments](https://docs.ablyft.com/guides/audiences-and-delivery/environments/): Control on which site an experiment runs.
- [JavaScript API](https://docs.ablyft.com/developers/reference/javascript-api/push/): Activate and deactivate pages from your code.

