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

# FactFinder WebComponents

> Beispiele für die Integration der FactFinder-Suche über die FactFinder WebComponents in einen WEBSALE-Shop, von der Skripteinbindung bis zum Nachladen der Produktboxen.

Für neue Integrationen der FactFinder-Suche sind die FactFinder WebComponents der vorgesehene Weg. Diese Seite zeigt an Beispielen, wie eine solche Integration in einem WEBSALE-Shop aussehen kann.

> [!WARNING]
>
> Die Beispiele auf dieser Seite veranschaulichen das Prinzip, sie sind nicht verbindlich. Maßgeblich für alle Integrationsschritte ist die offizielle FactFinder-Dokumentation. Die hier gezeigten Codeausschnitte erheben keinen Anspruch auf Vollständigkeit oder Aktualität, und WEBSALE übernimmt keine Garantie für ihre Funktionsfähigkeit.

Die offizielle Dokumentation von FactFinder finden Sie hier:

* [FactFinder WebComponents Guide](https://web-components.fact-finder.de/documentation/5.x/install-dist)
* [FactFinder WebComponents API](https://web-components.fact-finder.de/api/4.x/ff-communication)

## Skripte auf allen Seiten einbinden

Fügen Sie die WebComponents-Skripte global in den `<head>`-Bereich ein (beispielsweise über incl\_fast\_includes.htm), damit die Komponenten überall verfügbar sind.

```
<head>
  <!-- … weitere Head-Inhalte … -->

  <!-- Polyfills für ältere Browser -->
  <script src="../bower_components_4/dist/vendor/custom-elements-es5-adapter.js"></script>
  <script src="../bower_components_4/dist/vendor/webcomponents-loader.js"></script>

  <!-- FactFinder WebComponents Bundle -->
  <script defer src="../bower_components_4/dist/bundle.js"></script>

  <!-- … -->
</head>
```

**Hinweis:** Bundles variieren je nach Version/Setup.

## Suchformular und Eingabefeld

Das Suchformular stellt die Eingabe für den Suchbegriff bereit.

### Sucheingabefeld

Statt der bisherigen WEBSALE-Formular-Tags (`~FORM-QuickSearch~`, `~WS-Search_Input~`) wird hier die passende FactFinder WebComponents-Komponente verwendet.

Da ein Suchfeld in der Regel auf allen Shop-Seiten verfügbar sein soll, empfiehlt sich die Einbindung in die `incl_fast_includes.htm`.

```
<form id="ffsearchform" action="~URL-Homepage~" method="get" name="ffsearchform" accept-charset="ISO-8859-1">

    <input type="hidden" name="act" value="search">

    <ff-searchbox suggest-onfocus="false" hide-suggest-onblur="false">
        <input placeholder="Search..." />
        <button type="submit" value="Suchen"></button>
    </ff-searchbox>

</form>
```

**Hinweis zur Zeichencodierung:** Es kann auch `accept-charset="UTF-8"` umgestellt werden, damit Sonderzeichen robuster verarbeitet werden.

### Suggest unter dem Eingabefeld (optional)

Wenn der Funktionsumfang Suggest umfasst, kann danach die entsprechende Komponente direkt unterhalb des Eingabefelds eingebunden werden:

```
<ff-suggest>
  ...
  <ff-suggest-item>
    ...
  </ff-suggest-item>
  ...
</ff-suggest>
```

### Kommunikation einrichten

Integrieren Sie auf jeden Fall die FactFinder-Kommunikationskomponente (`<ff-communication>`). Diese sorgt für die Verbindung zur FactFinder-Instanz (Session-ID, Channel, Seitenkontext wie Kategorie/Suche).

Wichtig: Pro Seite genau eine Instanz einbinden.

```
<ff-communication url="https://<Ihre ID>.fact-finder.de/fact-finder"
  version="ng"
  api="v4"
  channel="<Ihr FactFinder Communication Channel, z.B. Syndigo_DE>"
  use-personalization="{AC-AgreementMadeForID(<Ihre ConsentLayerID>)}true{/AC-AgreementMadeForID(<Ihre ConsentLayerID>)}{!AC-AgreementMadeForID(<Ihre ConsentLayerID>)}false{/!AC-AgreementMadeForID(<Ihre ConsentLayerID>)}"
  sid="~WS-SID~"
  use-cache="true"

  <!-- Mögliche Parameter für die Kategorieseiten, z.B. ws_category.htm -->
  {ST-CatPage}
    category-page="filter=Categories:{CAT-PathData}~DC-Int1_set(0)~{@CAT-PathRegular}~DC-Int1_inc~{!DC-Int1(1)} &raquo; {/!DC-Int1(1)}~CAT-Name~{/@CAT-PathRegular}{/CAT-PathData}
    add-params="filter=marke:$CAT_Name$" <!-- z.B. für Markenseiten -->
  {/ST-CatPage}

  <!-- Mögliche Parameter für die Suchergebnisseite ws_search.htm -->
  ~DC-FPTemplatename_set($WS-TemplateName$)~
  {DC-FPTemplatename(ws_search.htm)}
    add-params="act=search"
    default-query="*"
    search-immediate
  {/DC-FPTemplatename(ws_search.htm)}

  >
</ff-communication>
```

**Hinweis:** Das obige Snippet ist ein Auszug. Die vollständige Parametermatrix (inkl. Versionsunterschieden) finden Sie in der offiziellen FactFinder-Dokumentation und müssen sie **projektspezifisch** (Kanal, API-Version, Personalisierung, Caching, Category Context etc.) anpassen:
[https://web-components.fact-finder.de/api/4.x/ff-communication#tab=api](https://web-components.fact-finder.de/api/4.x/ff-communication#tab=api)

### FactFinder WebComponents Version beachten

Bitte die Hauptversion des Projekts (4.x vs. 5.x) prüfen und in der FactFinder-Doku die passende Integrationsvariante wählen.

Bei 4.x empfiehlt FactFinder, `<ff-communication>` möglichst früh im `<body>` zu platzieren. In 5.x erfolgt die Einbindung über das bereitgestellte Bundle beziehungsweise Dist. Passen Sie die Integration entsprechend Ihrem Setup an.

Offizielle FactFinder WebComponents-Doku (Version wählen):
[FactFinder WebComponents Dokumentation](https://web-components.fact-finder.de/documentation/5.x/install-dist)

## Grundfunktionen für FactFinder WebComponents

### ResultDispatcher & EventAggregator einbinden

Für die FactFinder WebComponents werden die beiden zentralen Ereignis-Schnittstellen ResultDispatcher und EventAggregator benötigt. Sie werden, wie in der [FactFinder-Dokumentation](https://web-components.fact-finder.de/api/5.x/core-overview) beschrieben, initialisiert und angebunden (typischerweise nach `ffReady`, alternativ versionsabhängig nach `WebComponentsReady`).

Das globale Skript wird einmal pro Seite eingebunden, auf der eine FactFinder-Suche ausgelöst werden kann, also überall dort, wo ein Suchfeld vorhanden ist bzw. eine `<ff-communication>` auf der Seite steht.

```
<script>
  document.addEventListener("ffReady",function(){
    factfinder.communication.ResultDispatcher.subscribe("result",function(resultData){

      // {WS-TplComment} URL Parameter sollen beim ersten aufruf nicht angezeigt werden {/WS-TplComment}
      // {ST-CatPage}
      document.querySelector("ff-communication").setAttribute("use-url-parameters","true");
      document.querySelector("ff-communication").setAttribute("parameter-whitelist","filter,page,sort");
      // {/ST-CatPage}

      // {WS-TplComment} Preise in richtiges Format bringen {/WS-TplComment}
      var ffRecords = resultData.records
      for(i = 0; i < ffRecords.length; i++){
        if(ffRecords[i].record.Price == 0){
          ffRecords[i].record.Price = "";
        }
        else {
          ffRecords[i].record.Price = new Intl.NumberFormat('%%LanguageFormat%%', { style: 'currency', currency: '~WS-Currency~' }).format(ffRecords[i].record.Price)
        }
      }

      // {WS-TplComment}Platzhalter Elemente für sauberes Laden der Web Components{/WS-TplComment}
      var unresolvedPlaceholder = document.querySelectorAll(".unresolvedPlaceholder");
      for(i = 0; i < unresolvedPlaceholder.length; i++){
        unresolvedPlaceholder[i].style.setProperty("display", "none", "important");
      }
      var unresolvedElement = document.querySelectorAll(".unresolvedElement");
      for(i = 0; i < unresolvedElement.length; i++){
        unresolvedElement[i].style.removeProperty("display");
      }

      // {WS-TplComment} Ergebnis-/Fehlerzustände anzeigen (NoResult-Alternative entfällt) {/WS-TplComment}
      var result = resultData.resultCount;
      if(result > 0){
        document.getElementById("wsFFnoResult").style.display = "none";
        document.getElementById("wsFFerror").style.display = "none";
        document.getElementById("wsFFintegration").style.display = "block";
      }
      if(result === 0){
        document.getElementById("wsFFintegration").style.display = "none";
        document.getElementById("wsFFnoResult").style.display = "none"; // NoResult-Ansicht nicht genutzt
        document.getElementById("wsFFerror").style.display = "block";   // nur Fehler anzeigen
      }

    });

    factfinder.communication.EventAggregator.addFailCallback(function (event) {
      document.getElementById("wsFFnoResult").style.display = "none"; // NoResult-Ansicht nicht genutzt
      document.getElementById("wsFFerror").style.display = "block";
      document.getElementById("wsFFintegration").style.display = "none";

    });

  });

</script>
```

Weiterführende API-Infos zu ResultDispatcher und EventAggregator finden Sie in der [FactFinder Dokumentation](https://web-components.fact-finder.de/api/5.x/core-overview) (Bitte passende Integrationsvariante wählen)

### FactFinder WebComponents integrieren

Nach dem Grundskript können die WebComponents auf den Suchergebnisseiten (beispielsweise Kategorie und Suche) verwendet werden. Im Folgenden ein minimales Beispiel für Filter (ASN) und Ergebnisliste.

#### Filter (ASN)

```
<ff-asn>
  <!-- Beispiel: Gruppierter Filter (z. B. Kategorie/Marke) -->
  <ff-asn-group for-group="Categories" select-box="false" opened="true">
    <ff-asn-group-element></ff-asn-group-element>
  </ff-asn-group>

  <!-- Beispiel: Wertebereich als Slider (z. B. Preis) -->
  <ff-asn-group-slider opened="true">
    <ff-slider-control submit-on-input="true">
      <ff-slider></ff-slider>
    </ff-slider-control>
  </ff-asn-group-slider>
</ff-asn>
```

**Hinweis:** `for-group` muss dem Gruppennamen im FactFinder-Kanal entsprechen (Sprach-/Kanalbezeichnungen beachten).

#### Ergebnisse

```
<ff-record-list>
    <ff-record>
        <img src="{{record.altPicture}}" alt="">
        {{record.Name}}
    </ff-record>
</ff-record-list>
```

#### Optionaler Fehler-Container

```
<div id="wsFFerror" style="display:none">
  Es ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.
</div>
```

## Produkte in der Suchergebnisliste nachladen

Die Produkt­ergebnisse können zwar direkt über die FactFinder WebComponents gerendert werden. Für die Funktions­parität mit WEBSALE (beispielsweise Sofort-Bestellung aus der Liste, Auf-die-Merkliste-legen aus der Liste“, Variantenauswahl etc.) sowie die Datenaktualität empfiehlt sich jedoch ein Hybridansatz:

* Trefferermittlung, Paging und Filter: FactFinder WebComponents
* Produktbox-Rendering: Nachladen über die WEBSALE Template Engine

Vorteile des Nachladens via WEBSALE Template Engine:

* Zugriff auf alle WEBSALE-Funktionen der Produktlisten (beispielsweise Merkliste, Sofort-Bestellung etc.)
* Datenkonsistenz mit der Shop-Datenbank. Produkte, die bei FactFinder noch vorhanden sind, im Shop jedoch nicht mehr, werden beim Nachladen erkannt und der leere Produktcontainer wird entfernt (kein Layout-Sprung).

### Script mit den WEBSALE AJAX-Funktionen

```
<script>
  // Start-/Fehler-Hooks (können leer bleiben oder Logging/UI anzeigen)
  function ws_AJAXloadFFWCStart(){}
  function ws_AJAXloadFFWCError(){}

  // Erfolg: leere Produktcontainer sauber entfernen (verhindert Sprünge)
  function ws_AJAXloadFFWCResponseSuccess(){
    // {WS-TplComment} Entfernt Container ohne nachgeladenen Inhalt. {/WS-TplComment}
    var ffProductRecords = document.querySelectorAll('ff-record [data-ff-number]');
    for (var i = 0; i < ffProductRecords.length; i++) {
      if (!(ffProductRecords[i].children.length > 0)) {
        ffProductRecords[i].parentElement.remove();
      }
    }
  }

  // Hauptfunktion: IDs sammeln und Template via AJAX laden
  function wsFFProductsReady(){
    var resultList = document.querySelectorAll("[data-ff-number]");
    var payload = "ws_loadtpl_pl=y";
    var elementsFound = false;

    for (var i = 0; i < resultList.length; i++) {
      elementsFound = true;
      payload += "&ws_pl_" + (i + 1) + "=" + resultList[i].getAttribute("data-ff-number");
    }

    if (elementsFound) {
      ws_AJAXloadTemplatePOST(
        "~WS-AJAXLoadTpl(incl_web_components_products.htm)~",
        "~WS-Charset~",
        ws_AJAXloadFFWCStart,      // beforeSend
        ws_AJAXloadFFWCStart,      // onStart (ggf. identisch)
        'ws_AJAXloadFFWCResponseSuccess()', // onSuccess
        'ws_AJAXloadFFWCError()',           // onError
        payload
      );
    }
  }

  // WebComponents sind bereit: auf DOM-Updates der Ergebnisliste reagieren
  document.addEventListener("WebComponentsReady", function () {
    var list = document.querySelector("ff-record-list");
    if (list !== null) {
      list.addEventListener("dom-updated", function () {
        wsFFProductsReady();
      });
    }
  });
</script>
```

**Hinweis:** Für die Nutzung von WEBSALE Ajax-Funktionen wird die WEBSALE JavaScript-Bibliothek benötigt. Weitere Informationen zur [WEBSALE JavaScript-Bibliothek](https://doku.websale.net/index.html?guide_jsjq.html) finden Sie [hier](https://doku.websale.net/index.html?guide_jsjq.html).

Eine Übersicht über [verfügbare Versionen](https://doku.websale.net/index.html?mats_wsjsbibliothek.html) und Module der WEBSALE JavaScript-Bibliothek finden Sie [hier](https://doku.websale.net/index.html?mats_wsjsbibliothek.html).

### Platzhalter-Container auf der Ergebnis-Seite (Kategorie / Suche)

```
<body>
  ...

  <div id="wsFFintegration">
  ...

  <ff-record-list class="unresolvedElement">
    <ff-record>
      <div id="wsFFProductBox{{id}}" data-ff-number="{{id}}"></div>
    </ff-record>
  </ff-record-list>
  ...
  </div>
  ...
</div>
```

### Neues Template: `incl_web_components_products.htm`

Dieses Template wird im Script über den Aufruf
`ws_AJAXloadTemplatePOST("~WS-AJAXLoadTpl(incl_web_components_products.htm)~", …)`
nachgeladen.

Es liefert für jede von FactFinder gelieferte Produkt-ID die eigentliche Produktbox zurück.

```
...
{WS-PRListFromLoadTplLink_data}
  {@WS-PRListFromLoadTplLink_data}
    {PR-LoadData($WS-PRListFromLoadTplLink_id$,1)}
      <WS-Ajax-wsFFProductBox~WS-PRListFromLoadTplLink_id~>
        {WS-TplComment}<!-- Lade Produktblock aus der Fast-Include -->{/WS-TplComment}
        ~WS-Fast_Include(Incl-ProductBox)~
      </WS-Ajax-wsFFProductBox~WS-PRListFromLoadTplLink_id~>
    {/PR-LoadData($WS-PRListFromLoadTplLink_id$,1)}
  {/@WS-PRListFromLoadTplLink_data}
{/WS-PRListFromLoadTplLink_data}
...
```

Das Template kann bei Bedarf auch anders heißen. Wichtig ist, dass der Name dann im Script angepasst wird.

## Verwandte Themen

* Wegweiser: [Integration von FACT-Finder](https://dokumentation.websale.de/v8s/integration-von-fact-finder/integration-von-fact-finder.md)
* [FACT-Finder: Filter, Sortierung und Navigation](https://dokumentation.websale.de/v8s/integration-von-fact-finder/fact-finder-filter-sortierung-und-navigation.md)
* [FACT-Finder: Kampagnen](https://dokumentation.websale.de/v8s/integration-von-fact-finder/fact-finder-kampagnen.md)


## Related topics

- [Integration von FACT-Finder](https://dokumentation.websale.de/v8s/integration-von-fact-finder/integration-von-fact-finder.md)
- [FACT-Finder-Kampagnen](https://dokumentation.websale.de/v8s/integration-von-fact-finder/fact-finder-kampagnen.md)
- [FACT-Finder: Filter, Sortierung und Navigation](https://dokumentation.websale.de/v8s/integration-von-fact-finder/fact-finder-filter-sortierung-und-navigation.md)
- [E-Search_ (Blättern und Treffer pro Seite)](https://dokumentation.websale.de/v8s/referenz/tags/e-search/blaettern-und-treffer-pro-seite.md)
- [E-Search_ (Sortierung)](https://dokumentation.websale.de/v8s/referenz/tags/e-search/sortierung.md)


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