> ## 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.

# E-PSEO_ (SEO content for products)

> Build the input form of the SEO mode: SEO product name, main category index, twenty free SEO fields, field names, error messages and feedback.

In SEO mode, an SEO specialist opens the shop with a separate password and maintains additional content directly on the product detail view: an SEO product name for the speaking URL, a main category index, and up to twenty free fields for page title, description and whatever else is needed.

The input fields are not in the product detail view itself but in a separate template. You enter it in the shop configuration `shop.config` in the `SEOProductFields` section under the `Template` parameter and pull it into the page with `~WS-Module(product_seo)~`. The tags on this page apply exclusively in this template.

Guide: SEO content for products · Reference: SEOProductFields section · Reference: WS-Module()

> [!WARNING]
>
> The call to `WS-Module(product_seo)` belongs inside an `ST-SeoMode` range. Without it, ordinary visitors also see the input form.

Reference: ST-SeoMode

> [!NOTE]
>
> The maintained content is not output in the shop by these tags but by the `PR-SeoFreeField1…20` tags in the product detail view. This page only describes the maintenance interface.

Reference: PR-SeoFreeField1…20

## Can content be maintained in this subshop at all

Connected subshops receive their SEO data, like their product data, automatically from the main subshop. Maintenance therefore only takes place there. `E-PSEO_Connected_Subshop` is the first decision in the template.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{E-PSEO_Connected_Subshop}
   <p>
      In diesem Subshop lässt sich kein SEO-Content bearbeiten.
      Bitte nehmen Sie Ihre Änderungen im Subshop ~E-PSEO_Connected_Subshop~ vor.
   </p>
{/E-PSEO_Connected_Subshop}

{!E-PSEO_Connected_Subshop}
   <!-- hier stehen die Eingabefelder -->
{/!E-PSEO_Connected_Subshop}
```

> [!WARNING]
>
> The range applies **positively** when maintenance is **not** possible here. The input form therefore belongs in the negative branch. If you mix this up, you build a form whose submission the shop always rejects with the `ErrorConnectedSubshop` message.

> [!NOTE]
>
> As a single tag, `E-PSEO_Connected_Subshop` outputs the ID of the subshop in which maintenance must take place. Mention it in the notice, otherwise the SEO specialist has to guess where to switch to.

## The form

Both forms of the SEO mode, the one for saving and the one for resetting, need the same three hidden fields: the context, the product index and the action name.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{!E-PSEO_Connected_Subshop}
   <form class="seoform" action="/websale8/" method="post" id="SeoFormEdit">
      <input type="hidden" name="Ctx" value="~WS-CTX~">
      <input type="hidden" name="pi" value="~PR-ProdIndex~">
      <input type="hidden" name="~E-PSEO_Action_Save~" value="true">

      <label for="seo-name">SEO-Produktname für die Adresse (maximal 127 Zeichen)</label>
      <input type="text" id="seo-name" name="~E-PSEO_Name_Input~" value="~E-PSEO_Name~">
      {E-PSEO_Error_Name}<p class="fehler">~E-PSEO_Error_Name~</p>{/E-PSEO_Error_Name}

      <label for="seo-maincat">Hauptkategorieindex (maximal 255 Zeichen)</label>
      <input type="text" id="seo-maincat" name="~E-PSEO_MainCatIndex_Input~" value="~E-PSEO_MainCatIndex~">
      <input type="hidden" name="~E-PSEO_MainCatIndex_Hidden~" value="yes">
      {E-PSEO_Error_MainCatIndex}<p class="fehler">~E-PSEO_Error_MainCatIndex~</p>{/E-PSEO_Error_MainCatIndex}

      <label for="seo-feld1">SEO-Feld 1, beispielsweise für den Seitentitel (maximal 4000 Zeichen)</label>
      <textarea id="seo-feld1" name="~E-PSEO_Field1_Input~">~E-PSEO_Field1~</textarea>
      <input type="hidden" name="~E-PSEO_Field1_Hidden~" value="yes">
      {E-PSEO_Error_Field1}<p class="fehler">~E-PSEO_Error_Field1~</p>{/E-PSEO_Error_Field1}

      <button type="submit">Eingaben speichern</button>
   </form>

   <form class="seoform" action="/websale8/" method="post" id="SeoFormReset">
      <input type="hidden" name="Ctx" value="~WS-CTX~">
      <input type="hidden" name="pi" value="~PR-ProdIndex~">
      <input type="hidden" name="~E-PSEO_Action_Reset~" value="true">
      <button type="submit">Eingaben zurücksetzen</button>
   </form>
{/!E-PSEO_Connected_Subshop}
```

> [!WARNING]
>
> Without the product index in the `pi` field, the module aborts and outputs nothing at all. This is the most common cause of a form that leaves an empty page after submission.

> [!NOTE]
>
> `E-PSEO_Action_Save` and `E-PSEO_Action_Reset` only provide the technical name. They therefore go into the `name` attribute, not the value. You can set the same name again on the submit button, but this is not necessary in addition to the hidden field.

### The field names

Each input field has up to three tags following the same pattern.

| Notation | Provides |
| - | - |
| `E-PSEO_<Feld>` | the saved content, and as a range, the check whether it already contains something |
| `E-PSEO_<Feld>_Input` | the field name for the input element |
| `E-PSEO_<Feld>_Hidden` | the field name for the associated hidden field |

`<Feld>` stands for `Name`, `MainCatIndex` or `Field1` to `Field20`.

> [!WARNING]
>
> The hidden field from `_Hidden` belongs with every SEO field and with the main category index. The module only applies a value if either something is in it **or** the associated hidden field was sent along. Without the hidden field, a field that has once been filled can never be emptied again; the old content simply remains when saving.

> [!NOTE]
>
> The SEO product name does not need a hidden field and therefore has no `_Hidden` tag. It is always applied and can be emptied at any time.

> [!WARNING]
>
> Always take the field names from the `_Input` and `_Hidden` tags. A self-chosen name does not reach the module, and the input is lost when saving.

### The lengths

| Field | Maximum length |
| - | - |
| `E-PSEO_Name` | 127 characters |
| `E-PSEO_MainCatIndex` | 255 characters |
| `E-PSEO_Field1` to `E-PSEO_Field20` | 4000 characters |

> [!WARNING]
>
> The SEO product name must be unique across the shop because it becomes the product's URL. If someone assigns a name that already belongs to another product, the module rejects the save with the `ErrorNameAlreadyExists` message.

> [!NOTE]
>
> If even a single field is rejected when saving, the module saves **nothing at all**. The input remains in the form, and the affected fields show their error message. So the SEO specialist loses nothing but must fix all issues before anything is saved.

## Errors and feedback

| Tag | Effect |
| - | - |
| `E-PSEO_Error` | applies if something went wrong when saving, and outputs the message text |
| `E-PSEO_Success` | applies if the input was saved |
| `E-PSEO_Name_Changed` | applies if the SEO product name was changed |
| `E-PSEO_Error_Name` | the message for the SEO product name |
| `E-PSEO_Error_MainCatIndex` | the message for the main category index |
| `E-PSEO_Error_Field1…20` | the message for the respective SEO field |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{E-PSEO_Error}
   <div id="SeoProductError">
      <p>Es ist ein Fehler aufgetreten.</p>
      <p>~E-PSEO_Error~</p>
   </div>
{/E-PSEO_Error}

{E-PSEO_Success}
   <div id="SeoProductSuccess">
      <p>Ihre Eingaben wurden gespeichert.</p>
      {E-PSEO_Name_Changed}
         <p>Der SEO-Produktname hat sich geändert. Die neue Adresse des Produktes
            wird erst nach dem nächsten Generieren im TopRank-Manager wirksam.</p>
      {/E-PSEO_Name_Changed}
   </div>
{/E-PSEO_Success}
```

> [!NOTE]
>
> `E-PSEO_Success` and `E-PSEO_Name_Changed` are pure ranges without text output. You write the text into the template yourself.

> [!WARNING]
>
> All message texts are located in the shop configuration `shop.config` in the `SEOProductFields-Text` section, not in the template. If an entry is missing there, the message stays empty, and the SEO specialist sees an error without a reason. The required entries are `ErrorNameTooLong`, `ErrorFieldTooLong`, `ErrorNameAlreadyExists`, `ErrorConnectedSubshop` and `ErrorMainCatIndexTooLong`.

Reference: SEOProductFields-Text section

> [!NOTE]
>
> `E-PSEO_Name_Changed` is the place for the notice that the product's speaking URL has not been switched yet. It is only created during the next generation run in the TopRank Manager, not when saving.

## Reloading via AJAX

`E-PSEO_Ajax` applies if the module was loaded via an AJAX call. Use it to delimit the area that should be replaced after saving.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div id="SEOFields">
   {E-PSEO_Ajax}<WS-Ajax-SEOFields>{/E-PSEO_Ajax}

   <!-- Eingabefelder -->

   {E-PSEO_Ajax}</WS-Ajax-SEOFields>{/E-PSEO_Ajax}
</div>
```

> [!WARNING]
>
> The opening and closing markers must have the same name, and this name must match the ID of the surrounding element. A typo here means the shop replaces nothing after saving, without reporting an error.

> [!NOTE]
>
> Without AJAX, the entire product page is reloaded after saving. The advantage is that a change to the page title can be checked in the browser immediately. With the AJAX variant, only the enclosed area is refreshed.

Reference: WS-Ajax-"ID" · Guide: AJAX functions

## WEBSALE tags in the SEO fields

After a written order and technical activation, the SEO fields themselves may contain WEBSALE tags. They are then resolved when output in the shop.

> [!WARNING]
>
> So that the SEO specialist sees the tag itself in the input field and not its result, wrap the content in `WS-NoParsing`. Without this range, they only see the resolved result after saving and can neither check nor correct the tag.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<textarea id="seo-feld1" name="~E-PSEO_Field1_Input~">{WS-NoParsing}~E-PSEO_Field1~{/WS-NoParsing}</textarea>
```

Reference: WS-NoParsing

## Tag overview

| Tag | Single tag | Range tag | Negative range tag | Loop tag |
| - | - | - | - | - |
| `E-PSEO_Connected_Subshop` | yes | yes | yes | – |
| `E-PSEO_Action_Save` | yes | – | – | – |
| `E-PSEO_Action_Reset` | yes | – | – | – |
| `E-PSEO_Name` | yes | yes | yes | – |
| `E-PSEO_Name_Input` | yes | – | – | – |
| `E-PSEO_MainCatIndex` | yes | yes | yes | – |
| `E-PSEO_MainCatIndex_Input` | yes | – | – | – |
| `E-PSEO_MainCatIndex_Hidden` | yes | – | – | – |
| `E-PSEO_Field1…20` | yes | yes | yes | – |
| `E-PSEO_Field1…20_Input` | yes | – | – | – |
| `E-PSEO_Field1…20_Hidden` | yes | – | – | – |
| `E-PSEO_ProdIndex` | yes | – | – | – |
| `E-PSEO_Error` | yes | yes | yes | – |
| `E-PSEO_Error_Name` | yes | yes | yes | – |
| `E-PSEO_Error_MainCatIndex` | yes | yes | yes | – |
| `E-PSEO_Error_Field1…20` | yes | yes | yes | – |
| `E-PSEO_Success` | – | yes | yes | – |
| `E-PSEO_Name_Changed` | – | yes | yes | – |
| `E-PSEO_Ajax` | – | yes | yes | – |

All tags on this page are permitted in the template for the product SEO input fields, which is entered in the shop configuration `shop.config` in the `SEOProductFields` section under the `Template` parameter.

> [!NOTE]
>
> `E-PSEO_ProdIndex` outputs the product index to which the displayed fields belong. In the form, you can use it to replace `~PR-ProdIndex~`, which has the advantage that the value comes from the module itself and not from the surrounding shop template.

## Related topics

* Guide: SEO content for products
* Guide: SEO URLs
* Reference: SEOProductFields section
* Reference: SEOProductFields-Text section
* Reference: PR-SeoFreeField1…20


## Related topics

- [SEO content for products](https://dokumentation.websale.de/en/v8s/seo/seo-content-fuer-produkte.md)
- [SEO optimization with TopRank](https://dokumentation.websale.de/en/v8s/seo/seo-optimierung-mit-toprank.md)
- [PR- (Images and links)](https://dokumentation.websale.de/en/v8s/referenz/tags/pr/bilder-und-links.md)
- [Basics and technology](https://dokumentation.websale.de/en/v8s/referenz/konfigurationen/shopkonfiguration-shop-config/grundlagen-und-technik.md)
- [content - Catalogue (categories & products)](https://dokumentation.websale.de/en/konfiguration/content-katalog-kategorien-produkte.md)


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