> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Counters and comparisons in the template

> Show and hide areas depending on counter values and strings, and number elements in loops uniquely.

A template does not always output the same thing. Three tools help you make the output depend on conditions or vary it within a loop.

| Tool | Purpose |
| - | - |
| `DC-Counter1` to `DC-Counter3` | Show areas only if something else was **not** shown before |
| `WS-Counter` and `WS-Counter2` | Number elements in a loop, for unique IDs or alternating classes |
| `DC-CompareStringInList` | Show areas depending on whether a value appears in a list |

The two counter families differ fundamentally: you reset the DesignControl counters yourself and increment them deliberately to build conditions. The WS counters only run forward and are used for numbering.

## Showing areas depending on counter values

The DesignControl counters `DC-Counter1` to `DC-Counter3` are at 0 on every page call. They can be incremented and reset as often as you like. The value is checked with the area tag of the same name.

| Tag | Effect |
| - | - |
| `~DC-Counter1_reset~` | sets the counter to 0 |
| `~DC-Counter1_inc~` | increments the counter by 1 |
| `~DC-Counter1~` | outputs the value |
| `{DC-Counter1(0)}` | area applies if the counter is 0 |

> [!NOTE]
>
> There are exactly three counters. `DC-Counter4` and higher return nothing.

> [!NOTE]
>
> The area tag can contain several values, separated by commas. `{DC-Counter1(0,2,4)}` applies for each of these three values.

> [!WARNING]
>
> There is no counterpart to `_inc`. The counter can only be incremented or reset to 0, not decremented and not set to a specific value. If you need that, use `DC-Int1` to `DC-Int3`, which support `_set`, `_add` and `_sub`.

### Example: showing the first available product list

A special list is to appear at the bottom of the product detail view. The first choice is Bought-Together products. If there are none, accessory products should appear, and if those are missing too, complementary products. Exactly one of the three lists should be shown in the end.

The counter keeps track of whether something has already been output.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
~DC-Counter1_reset~

<!-- 1. Wahl: Bought-Together-Produkte -->
{CAT-AdvData($BT-Links,5)}
   ~DC-Counter1_inc~
   {@PR-Data}
      Produktdaten der Bought-Together-Produkte
   {/@PR-Data}
{/CAT-AdvData($BT-Links,5)}

<!-- 2. Wahl: Zubehör, nur wenn oben nichts kam -->
{DC-Counter1(0)}
   {CAT-AdvData($C-Links,5)}
      ~DC-Counter1_inc~
      {@PR-Data}
         Produktdaten des Zubehörs
      {/@PR-Data}
   {/CAT-AdvData($C-Links,5)}
{/DC-Counter1(0)}

<!-- 3. Wahl: ergänzende Produkte, nur wenn oben zweimal nichts kam -->
{DC-Counter1(0)}
   {CAT-AdvData($CS-Links,5)}
      {@PR-Data}
         Produktdaten der ergänzenden Produkte
      {/@PR-Data}
   {/CAT-AdvData($CS-Links,5)}
{/DC-Counter1(0)}
```

> [!NOTE]
>
> The last block no longer increments the counter. This is not an oversight: it is not queried afterwards. If you later add a fourth list, you must add the `~DC-Counter1_inc~` there.

> [!WARNING]
>
> The `~DC-Counter1_inc~` belongs **inside** the bracketing but **before** the data loop. If it is inside the loop, it counts up once per product, and the counter ends up at 5 instead of 1. For a simple check for 0 this makes no difference, but for any more precise check it does.

Reference: DC-Counter1…3 · DC-Counter1…3\_inc · DC-Counter1…3\_reset · CAT-AdvData() · PR-Data

Guide: Displaying Bought-Together products

## Numbering elements in loops

Within a loop, each element often needs its own number, for example for a unique HTML ID or for alternating class names. There are two independent counters for this.

| Tag | Effect |
| - | - |
| `~WS-Counter~` | outputs the value of the first counter |
| `~WS-CounterInc~` | increments the first counter by 1 and outputs it |
| `~WS-Counter2~` | outputs the value of the second counter |
| `~WS-Counter2Inc~` | increments the second counter by 1 and outputs it |

Both are at 0 on every page call and can only be incremented, not reset. This means they deliver unique numbers across an entire page.

> [!NOTE]
>
> `WS-Counter` and `WS-Counter2` are two separate counters. You can use both at the same time on the same page without them interfering with each other.

### Sequential numbering

A gallery view should give each tile its own class so that, for example, the third column can be addressed differently.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@PR-Data}
   <div class="category_box_~WS-CounterInc~">
      ~PR-Name~
   </div>
{/@PR-Data}
```

This results in `category_box_1`, `category_box_2`, `category_box_3` and so on.

### Unique IDs

An ID may only appear once on a page. In a loop over grouping products, the counter creates a separate ID for each form.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{ST-ParentProduct}
   {CAT-AdvData($ChildProducts,99)}
      {@PR-Data}
         <form action="~FORM-Product~" method="post" id="productform_catchilds_~WS-CounterInc~">
            ...
            <input type="submit" value="in den Warenkorb"
                   onclick="return ws_AJAXaddToBasket('productform_catchilds_~WS-Counter~',
                            '~BT-ProductAddToBasket_Ajax~', '~WS-Charset~')">
            ...
         </form>
      {/@PR-Data}
   {/CAT-AdvData($ChildProducts,99)}
{/ST-ParentProduct}
```

> [!WARNING]
>
> Note the difference in this example: the ID on the form uses `WS-CounterInc` and thus increments the counter. The call further down uses `WS-Counter` and only reads it. If `WS-CounterInc` were used there as well, the script would address a form that does not exist.

### Alternating numbering with modulo

`WS-Counter2` and `WS-Counter2Inc` accept a number as an argument. In that case, not the counter value is output, but its remainder when divided by this number.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<table>
   {@PR-Data}
      <tr>
         <td class="category_td_~WS-Counter2Inc(2)~">~PR-Name~</td>
      </tr>
   {/@PR-Data}
</table>
```

This alternately results in `category_td_1` and `category_td_2`, i.e. a color change from row to row.

> [!NOTE]
>
> The value range is between **1 and the argument**, both inclusive. `WS-Counter2Inc(3)` therefore returns 1, 2, 3, 1, 2, 3 and never 0. This differs from the usual modulo calculation, which would yield 0 to 2, and is exactly what you need for class names.

> [!WARNING]
>
> At counter value 0, the argument returns the maximum value. `~WS-Counter2(2)~` therefore outputs 2 before the first `Inc`, not 0. So only read the counter after you have incremented it at least once.

Reference: WS-Counter · WS-CounterInc · WS-Counter2() · WS-Counter2Inc()

Materials: Modulo calculation

## Showing areas depending on strings

`DC-CompareStringInList` checks whether a string appears in a list of strings. Both arguments support tag-in-tag, so you can use tags instead of fixed texts.

This is how a German shop shows buyers with Austria as their billing country a notice about the Austrian shop.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{A-CountryISO}
   {DC-CompareStringInList($A-CountryISO$,AUT)}
      ... Banner für Österreich ...
   {/DC-CompareStringInList($A-CountryISO$,AUT)}
{/A-CountryISO}
```

With several countries:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{A-CountryISO}
   {DC-CompareStringInList($A-CountryISO$,"DEU,AUT,CHE")}
      ... Banner für den deutschsprachigen Raum ...
   {/DC-CompareStringInList($A-CountryISO$,"DEU,AUT,CHE")}
{/A-CountryISO}
```

> [!WARNING]
>
> The quotation marks around the list are mandatory as soon as it contains more than one value. The tag expects **exactly two** parameters. Without quotation marks, the parser splits the list into individual parameters, and the tag becomes invalid.

> [!NOTE]
>
> The outer bracketing with `A-CountryISO` is not superfluous. It ensures that nothing is checked at all as long as the customer has not yet selected a billing country.

> [!NOTE]
>
> The tag only exists as an area tag and in the negated form. As a single tag, it returns nothing.

Reference: DC-CompareStringInList()

## Related topics

* Basics: Basics of tags
* Guide: Using free parameter tags
* Reference: DC-Int1…3


## Related topics

- [Using free parameter tags](https://dokumentation.websale.de/en/v8s/fortgeschrittene-designtechniken/freie-parameter-tags-verwenden.md)
- [PRC- (Product comparison)](https://dokumentation.websale.de/en/v8s/referenz/tags/prc-produktvergleich.md)
- [Product comparison](https://dokumentation.websale.de/en/frontend/funktionsubersicht/produktvergleich.md)
- [Template migration](https://dokumentation.websale.de/en/migration/migration-websale-v8s-neue-version/template-migration.md)
- [Shop, page and technology](https://dokumentation.websale.de/en/v8s/referenz/tags/ws/shop-seite-und-technik.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.