---
title: Artificial Pageviews - Web
description: Artificial pageviews are to be used when the site uses AJAX, SPA, PWA, or re-routes users without refreshing the page
lastUpdated: 22 January 2026
source_url:
  html: https://docs.contentsquare.com/en/web/artificial-pageviews/
  md: https://docs.contentsquare.com/en/web/artificial-pageviews/index.md
---

Use artificial pageviews when:

* An action completely changes the content displayed on the page without refreshing it and changing its URL (Ajax requests)
* The site is built with a Single Page Application (SPA) and any related frameworks (React, Angular)
* The user gets redirected to another step of a funnel without refreshing the page
* The site re-routes all the URL changes without refreshing the page
* The site is built as a Progressive Web App (PWA)
* Important modal windows (sometimes called popups or popins) are displayed

#### Modal tracking with artificial pageviews

To track a modal opening and closing while the user navigates your site, use artificial pageviews.

Send one artificial pageview when the modal is opened, and another one when the modal is closed. For example, this might be a click on the close button or a custom JavaScript event that fires when the modal is dismissed. For the close event, you can reuse the code snippet, updating the name or path parameter to indicate that this is a close event.

#### Stable URLs - Modal windows and artificial pageviews tracking

For tracking **modal windows or events that don't change the URL structure**, you'll need to use the Contentsquare **Trackpageview** functionality by following these methods and binding them to the correct action (button click/event trigger).

#### Dynamic URLs - Single Page Applications and History Change

In the event of the **URL structure being changed** on each view change, we can keep track of this by **firing the Main Tag again**: the tag will automatically detect that it was previously put in place on the site and fire a new pageview instead.

## Contentsquare Tag Configurator (CSTC)

Use the [Contentsquare Tag Configurator ↗](https://support.contentsquare.com/hc/en-us/articles/37271878716433-CSTC-Template-Artificial-Pageview) to implement artificial pageviews through a visual interface.

## Google Tag Manager (Template)

### Stable URLs

1. Open your container and go to the **templates** section ![](https://docs.contentsquare.com/_astro/main-1.BR8xO2Cv_Z1Rabw1.webp)

2. Select **Search gallery** ![](https://docs.contentsquare.com/_astro/main-2.CDPvDirB_Z1usb2F.webp)

3. Type in **`contentsquare`** and select the **Contentsquare - Artificial Pageview** option ![](https://docs.contentsquare.com/_astro/apv-1.Bzce9kSI_2o0fAd.webp)

4. Click **Add to workspace** ![](https://docs.contentsquare.com/_astro/apv-2.DX8B20r8_ZXrWeP.webp)

5. Confirm your choice by selecting **Add** ![](https://docs.contentsquare.com/_astro/main-5.SPp88Wgv_tc1tk.webp)

6. Go to the Tags section and click the **New** button to create a new tag ![](https://docs.contentsquare.com/_astro/add-tag.DuGAskV4_1e0yKr.webp)

7. Configure it by selecting the top-right button ![](https://docs.contentsquare.com/_astro/tag-config.krkkPQIC_19Jyy1.webp)

8. Type in **`contentsquare`** and select the **Contentsquare - Artificial Pageview** option ![](https://docs.contentsquare.com/_astro/apv-3.xL597kw3_10heN9.webp)

9. Select the tag and configure:

   * Select the Free text option and enter the value under `Artificial Pageview value`.
   * If there's a modal (sometimes called "popup") on your website and you need to deploy APV, then select `This is for the opening a popup` or `This is for the closing of a popup` in the drop-down.

   Note

   The value will be prefixed with `cs-popin-`. For instance `cs-popin-cart`, `cs-popin-wishlist`.

   ![](https://docs.contentsquare.com/_astro/apv-4.BK6q2p89_Zk14qR.webp)

### Dynamic URLs

1. Amend the Main tag configuration by **adding a new trigger** to it. ![](https://docs.contentsquare.com/_astro/new_trigger.B-oq_DNs_15R10X.webp)

2. Create a new trigger ![](https://docs.contentsquare.com/_astro/add_trigger.CPlZqQgy_Z2lUhcw.webp)

3. Select **"Choose a trigger type to begin setup..."**. ![](https://docs.contentsquare.com/_astro/choose_trigger.CDEj-0nO_ZnHEu7.webp)

4. In the list, select the **"History Change"** trigger. ![](https://docs.contentsquare.com/_astro/history_change.DYcRJtu0_ZiyWaN.webp)

5. **Save** your trigger. ![](https://docs.contentsquare.com/_astro/save_history_change.C8gCfaz4_Z1QNhHG.webp)

6. Select the **"Save"** button on the top right. ![](https://docs.contentsquare.com/_astro/save_final_triggers.C6m163aP_Z209RXL.webp)

## Google Tag Manager (Custom HTML)

### Stable URLs

1. Select **"Choose a tag type to begin setup..."**. ![](https://docs.contentsquare.com/_astro/gtm-main-2.Cx9dgCJT_Z2rUWBi.webp)

2. In the list, pick the **"Custom HTML"** tag. ![](https://docs.contentsquare.com/_astro/gtm-main-3.D8rqTH8-_lh7R7.webp)

3. Write the snippet to be fired in the **HTML field**. It should be similar to this:

   ```html
   <script type="text/javascript">
     window._uxa = window._uxa || [];
     window._uxa.push([
       "setQuery",
       window.location.search + (window.location.search ? "&" : "?") + "cs-popin-dedicated_query_string", { lifespan: 'onNextPageviewOnly' }
     ]);
     window._uxa.push([
       "trackPageview",
       window.location.pathname + window.location.hash.replace("#", "?__"), { lifespan: 'onNextPageviewOnly' }
     ]);
   </script>
   ```

   ![](https://docs.contentsquare.com/_astro/gtm-main-4.WOTyIdwT_2blgbK.webp)

4. Select **"Choose a trigger to make this tag fire..."**. ![](https://docs.contentsquare.com/_astro/gtm-main-5.BmTIMLVp_c4tnA.webp)

5. Create a new trigger to make this tag fire ![](https://docs.contentsquare.com/_astro/add_trigger.CPlZqQgy_Z2lUhcw.webp)

6. Select **"Choose a trigger type to begin setup..."**. ![](https://docs.contentsquare.com/_astro/choose_trigger.CDEj-0nO_ZnHEu7.webp)

7. In the list, pick the **"All Elements"** trigger. ![](https://docs.contentsquare.com/_astro/click_all_element.BlBhjAbD_Zz05AL.webp)

8. Check **"Some Clicks"** ![](https://docs.contentsquare.com/_astro/some_click.DQG2DBSN_TBVs0.webp)

9. Select **"Click Element"**, **"matches CSS selector"** and enter a **valid CSS** filter corresponding to the element you want to track.

   For example the valid CSS for:

   ```html
   <button class="btn btn primary">Submit</button>
   ```

   Will be:

   ```css
   .btn.btn.primary
   ```

   ![](https://docs.contentsquare.com/_astro/trigger_conditions.CpqLbeXq_ZteOIP.webp)

### Dynamic URLs

1. Amend the Main tag configuration by **adding a new trigger** to it. ![](https://docs.contentsquare.com/_astro/new_trigger.B-oq_DNs_15R10X.webp)

2. Create a new trigger ![](https://docs.contentsquare.com/_astro/add_trigger.CPlZqQgy_Z2lUhcw.webp)

3. Select **"Choose a trigger type to begin setup..."**. ![](https://docs.contentsquare.com/_astro/choose_trigger.CDEj-0nO_ZnHEu7.webp)

4. In the list, select the **"History Change"** trigger. ![](https://docs.contentsquare.com/_astro/history_change.DYcRJtu0_ZiyWaN.webp)

5. **Save** your trigger. ![](https://docs.contentsquare.com/_astro/save_history_change.C8gCfaz4_Z1QNhHG.webp)

6. Select the **"Save"** button on the top right. ![](https://docs.contentsquare.com/_astro/save_final_triggers.C6m163aP_Z209RXL.webp)

## Tealium

### Stable URLs

**Assign the event** you might already have in place a custom HTML snippet and write the snippet to be fired in the HTML field. It should be similar to this:

```html
<script type="text/javascript">
  window._uxa = window._uxa || [];
  window._uxa.push([
    "setQuery",
    window.location.search + (window.location.search ? "&" : "?") + "cs-popin-dedicated_query_string", { lifespan: 'onNextPageviewOnly' }
  ]);
  window._uxa.push([
    "trackPageview",
    window.location.pathname + window.location.hash.replace("#", "?__"), { lifespan: 'onNextPageviewOnly' }
  ]);
</script>
```

### Dynamic URLs

Create (or select an already existing) event that occurs on each history change or view re-routing. Assign this event to the Contentsquare extension.

## Adobe Launch

### Stable URLs

#### Artificial Pageviews

When setting up the rule, **make sure to target the specific event or condition** needed. For instance, for an add to bag action, you could either follow the click route:

![](https://docs.contentsquare.com/_astro/18-1.ChLqKm9n_Z2ic3mQ.webp)

Or the custom event route:

![](https://docs.contentsquare.com/_astro/18.7hhojld6_ZChzEK.webp)

Once you've chosen the desired event, you can select the Artificial Pageview tracking action from the Contentsquare extension.

![](https://docs.contentsquare.com/_astro/19.C5zEYyee_nkY1s.webp)

Depending on the pageview you'd need to track, you can **either specify the query** to be passed to the Contentsquare servers: ![](https://docs.contentsquare.com/_astro/20-1.Ci3CEvX-_U51WB.webp)

**Or, leave the input field empty**, which will allow our script to capture the current URL automatically: ![](https://docs.contentsquare.com/_astro/20.D7-BtAJN_2ihMPw.webp)

You can also use **Data Elements** as a query string for artificial pageviews. ![](https://docs.contentsquare.com/_astro/20-2.BkFa-5Gz_1htc2C.webp)

### Dynamic URLs

In the event of a SPA implementation, if the path/query automatically changes on each re-routing, utilise the built-in history change event to fire the CS tag on each of these occurrences. ![](https://docs.contentsquare.com/_astro/5-2.n-I9ZIIQ_21p70I.webp)

## Commanders Act

1. To add a new event, go to the "EDIT" step, and click "ADD EVENT" (1): ![](https://docs.contentsquare.com/_astro/add_event.CuQfcqzu_2bshcV.webp)

   A configuration window will appear, with several fields:

   * (1) "Name": Name of the event you wish to add
   * (2) "Id": The event’s ID (to be completed only if you know it and want to trigger the event based on its ID; otherwise, leave the field empty, and it will be generated automatically by Commanders Act)
   * (3) JavaScript code: Area where the event’s JavaScript code is entered
   * (4) "Use Tag Cleaner": Feature allowing you to "correct" the event (rewrites it in order to avoid JavaScript errors and makes it compatible with the container’s code)

   ![](https://docs.contentsquare.com/_astro/add_event_detail.CzxffRx9_ZoLmBf.webp)

2. Click "ADD" to add your event to the container.

3. Go to the tag library. Once there:

   1. Write "Event Injection" in the search engine
   2. Select the tag
   3. Add the tag

![](https://docs.contentsquare.com/_astro/event_injection.IGX-NM_k_1Ku46q.webp)

In case of tracking pageviews with Contentsquare, the code to be deployed should follow this guideline:

```javascript
window._uxa = window._uxa || [];
window._uxa.push(['trackPageview', <PATH_TO_SEND> ]);
```

(4) Go to your website; place the cursor on the element you wish to place an event on and do a right click. In the menu that opens up, select "Inspect Element". (5) In the console, once the element is highlighted, right-click again. (6) Choose "copy" from the menu. (7) > "Copy Selector".

Note

These actions on the site’s CSS are applicable to the Google Chrome browser only.

![](https://docs.contentsquare.com/_astro/find_selector.76dO9AUU_Z23SyGl.webp)

(8) If you know the element’s ID (starting with a #, copy and paste it in the #CSS\_PATH# field).

![](https://docs.contentsquare.com/_astro/css_path.DoMptTeK_Z2r75rW.webp)

(9) If you do not know or cannot find the ID, copy and paste the element’s information starting with "#" and replace " > "(space>space) with a single space in the code line.

![](https://docs.contentsquare.com/_astro/css_path2.DmAKh-OS_brgIg.webp)

(10) Copy and paste the line in the interface’s #CSS\_Path# field.

![](https://docs.contentsquare.com/_astro/css_path3.CaKSXgoC_Z1J3qjq.webp)

Now enter the ID of the event you wish to summon in the corresponding field.

Proceed to the deployment step as you do with other tags.

## Shopify

1. Within the main menu, select **Online Store > Themes**, then click the **Actions** drop-down menu, and **Edit Code**.

   ![](https://docs.contentsquare.com/_astro/shopify-interface-edit-code.Dh_bZBhg_tR5Vy.webp)

2. Open the relevant Liquid file where you want to trigger an artificial pageview based on your own JavaScript logic. You can put this in the main `theme.liquid` file or in a specific Liquid file.

   Let’s say you want to trigger this artificial pageview only when a certain action takes place like when an item is added to the cart. You would need to wrap this code inside your own condition, callback function, or event listener.

3. In the snippet below, replace `<PATH_TO_SEND>` with your unique path.

   ```html
   <script type="text/javascript">
     window._uxa = window._uxa || [];
     window._uxa.push(['trackPageview', <PATH_TO_SEND> ]);
   </script>
   ```

   You either hard-code a static value for the path like `Added_to_cart` or use Shopify’s [Liquid Objects ↗](https://shopify.dev/api/liquid/objects)/[Liquid Tags ↗](https://shopify.dev/api/liquid/tags) to grab the dynamic data from it like below:

   Tip

   Check out Shopify's [Liquid Object cheat sheet ↗](https://www.shopify.com/partners/shopify-cheat-sheet)

   ```html
   <script type="text/javascript">
     // Contentsquare Send Artificial Pageviews
     document.getElementById("AddToCart").addEventListener('click', function() {
         window._uxa = window._uxa || [];
         window._uxa.push(["trackPageview", "Added_to_cart_" + {{ custom_tag.value}}])
     });
   </script>
   ```

4. Insert this code after the main tracking tag block.

   The end result of adding this code into the Liquid file:

   ```html
   <!-- Contentsquare Tags Start -->
   <script type="text/javascript">
     // Contentsquare Main Tracking Tag
     (function () {
       window._uxa = window._uxa || [];
       if (typeof CS_CONF === "undefined") {
         window._uxa.push([
           "setPath",
           window.location.pathname + window.location.hash.replace("#", "?__")
         ]);
         var mt = document.createElement("script");
         mt.type = "text/javascript";
         mt.async = true;
         mt.src = "//t.contentsquare.net/uxa/769238b6e1309.js";
         document.getElementsByTagName("head")[0].appendChild(mt);
       } else {
         window._uxa.push([
           "trackPageview",
           window.location.pathname + window.location.hash.replace("#", "?__")
         ]);
       }
     });
   </script>


   <script type="text/javascript">
     // Contentsquare Send Artificial Pageviews
     document.getElementById("AddToCart").addEventListener('click', function() {
         window._uxa = window._uxa || [];
         window._uxa.push(["trackPageview", "Added_to_cart_" + {{ custom_tag.value}}])
     });
   </script>
   ```

5. To modify the entire path that is sent, use the `setPath` command:

   ```html
   <script type="text/javascript">
     // Contentsquare Send Artificial Pageviews
     document.getElementById("AddToCart").addEventListener('click', function() {
         window._uxa = window._uxa || [];
         window._uxa.push(["setPath", "Added_to_cart_" + {{ custom_tag.value }}]);
         window._uxa.push(["trackPageview"]);
     });
   </script>
   ```

   Note

   You don’t need to supply a second parameter in the `trackPageview` command when it is set in the `setPath` command above it.

   For more information, see the [`setPath` command](https://docs.contentsquare.com/en/web/sending-pageviews/#modifying-the-path).

6. To modify only the query string, use the `setQuery` command:

   ```html
   <script type="text/javascript">
     // Contentsquare Send Artificial Pageviews
     document.getElementById("AddToCart").addEventListener('click', function() {
         window._uxa = window._uxa || [];
         window._uxa.push(["setQuery", "Added_to_cart_" + {{ custom_tag.value }}]);
         window._uxa.push(["trackPageview"]);
     });
   </script>
   ```

Note

You don’t need to supply a second parameter in the `trackPageview` command when it is set in the `setQuery` command above it.

For more information, read about the [`setQuery` command](https://docs.contentsquare.com/en/web/sending-pageviews/#modifying-the-query-parameters).

## Custom HTML

To send a pageview, use the `trackPageview` command:

```html
<script type="text/javascript">
  window._uxa = window._uxa || [];
  window._uxa.push(['trackPageview', <PATH_TO_SEND>]);
</script>
```

`<PATH_TO_SEND>` is limited to 255 characters.

Just the path

The Tag prepends the domain and appends the query parameters.

Do not include the domain or the `#` character since everything which comes after is erased.

### Stable URLs

For instance, in case you wanted to keep track of the modal window appearing when adding an item to the cart:

```html
<script type="text/javascript">
  window._uxa = window._uxa || [];
  window._uxa.push([
    "setQuery",
    window.location.search + (window.location.search ? "&" : "?") + "cs-popin-dedicated_query_string", { lifespan: 'onNextPageviewOnly' }
  ]);
  window._uxa.push([
    "trackPageview",
    window.location.pathname + window.location.hash.replace("#", "?__"), { lifespan: 'onNextPageviewOnly' }
  ]);
</script>
```

### Dynamic URLs

#### With custom variables

```html
<script>
  (function () {
    window._uxa = window._uxa || [];
    try {
      if (typeof dataLayer !== "undefined") {
        for (var i = 0; i < dataLayer.length; i++) {
          window._uxa.push([
            "setCustomVariable",
            1,
            "Sample Variable",
            dataLayer[i].sampleVariable,
            3
          ]);
        }
      }
    } catch (e) {}
    if (typeof CS_CONF === "undefined") {
      window._uxa.push([
        "setPath",
        window.location.pathname + window.location.hash.replace("#", "?__")
      ]);
      var mt = document.createElement("script");
      mt.type = "text/javascript";
      mt.async = true;
      mt.src = "//t.contentsquare.net/uxa/{{YOUR_TAG_ID}}.js";
      document.getElementsByTagName("head")[0].appendChild(mt);
    } else {
      window._uxa.push([
        "trackPageview",
        window.location.pathname + window.location.hash.replace("#", "?__")
      ]);
    }
  })();
</script>
```

#### Without custom variables

```html
<script>
  (function () {
    window._uxa = window._uxa || [];
    if (typeof CS_CONF === "undefined") {
      window._uxa.push([
        "setPath",
        window.location.pathname + window.location.hash.replace("#", "?__")
      ]);
      var mt = document.createElement("script");
      mt.type = "text/javascript";
      mt.async = true;
      mt.src = "//t.contentsquare.net/uxa/{{YOUR_TAG_ID}}.js";
      document.getElementsByTagName("head")[0].appendChild(mt);
    } else {
      window._uxa.push([
        "trackPageview",
        window.location.pathname + window.location.hash.replace("#", "?__")
      ]);
    }
  })();
</script>
```

### Tracking a modal opening

To track a modal (or "popin") opening/closing during the user's navigation, use **artificial pageviews**.

1. A first artificial pageview needs to be sent when the modal is opened — the sent URL will be the current one, followed by a string of characters allowing you to identify the modal.

   ```html
   <script type="text/javascript">
     window._uxa = window._uxa || [];
     window._uxa.push([
       "setQuery",
       window.location.search + (window.location.search ? "&" : "?") + "cs-popin-dedicated_query_string", { lifespan: 'onNextPageviewOnly' }
     ]);
     window._uxa.push([
       "trackPageview",
       window.location.pathname + window.location.hash.replace("#", "?__"), { lifespan: 'onNextPageviewOnly' }
     ]);
   </script>
   ```

2. A second artificial pageview needs to be sent when the modal is closed. The sent URL will be the current one.

   ```html
   <script type="text/javascript">
     window._uxa = window._uxa || [];
     window._uxa.push([
       "trackPageview",
       window.location.pathname + window.location.hash.replace("#", "?__")
     ]);
   </script>
   ```

### Single Page Application

The Contentsquare Tracking tag sends only one pageview per full reload. In a Single Page Application (SPA), that would be only once per session.

To handle this, **an [artificial pageview](https://docs.contentsquare.com/en/web/artificial-pageviews/#custom-html) on every page change** is needed — use the "History Change" event which is available in most Tag Management Systems.

You can fire the following script on every page and on history change. It fires the main tag the first time and then sends an artificial pageview for each next call.

```html
<script type="text/javascript">
  window._uxa = window._uxa || [];
  /* First call */
  if (typeof CS_CONF === "undefined") {
    window._uxa.push([
      "setPath",
      window.location.pathname + window.location.hash.replace("#", "?__")
    ]);
    var mt = document.createElement("script");
    mt.type = "text/javascript";
    mt.async = true;
    mt.src = "//t.contentsquare.net/uxa/YOUR_TAG_ID.js";
    document.getElementsByTagName("head")[0].appendChild(mt);
  } else {
    /* Every next call */
    window._uxa.push([
      "trackPageview",
      window.location.pathname + window.location.hash.replace("#", "?__")
    ]);
  }
</script>
```

### Following a single page check-out

If your checkout only fires one full reload, the main tag will be called just once, and only one natural pageview will be sent.

We thus only collect:

* `shop.com/checkout/`

Instead of:

* `shop.com/checkout/step1`
* `shop.com/checkout/step2`
* `shop.com/checkout/step3`
* `shop.com/checkout/step4`

To achieve this result, it is necessary to:

1. Change the natural pageview URL (the first that was sent)

2. Send an artificial pageview for every step

Here is the corresponding code, which uses the [`setPath` function](https://docs.contentsquare.com/en/web/sending-pageviews/#modifying-the-path) and [artificial pageviews](https://docs.contentsquare.com/en/web/artificial-pageviews/#custom-html):

```javascript
/* 1. Change the natural URL pageview, before loading the main tag */


window._uxa = window._uxa || [];
window._uxa.push(["setPath", "checkout/step1"]);


(function () {
  var mt = document.createElement("script");
  mt.type = "text/javascript";
  mt.async = true;
  mt.src = "//t.contentsquare.net/uxa/YOUR_TAG_ID.js";
  document.getElementsByTagName("head")[0].appendChild(mt);
})();


/* ... Step Change Event ... */


/* 2. Send an artificial page for every step change*/


window._uxa = window._uxa || [];
window._uxa.push(["trackPageview", "checkout/step" + n]);


/* Repeat step 2 as much as required */
```
