Clerk (JTL-Shop 5)

Einleitung

Dieses Plugin integriert den Clerk.io Service in Ihren JTL-Shop.

Somit sind personalisierte Produktempfehlungen, eine erweiterte Suche, individualisierte Slider und vieles weitere möglich.

Installation und Update

Systemvoraussetzungen

  • JTL-Shop 5.1+ (und die beinhalteten Bibliotheken)

  • JTL-Wawi 1.5

  • MySQL 5.7

  • Linux mit Apache 2 / Litespeed (andere Konstellationen sind möglich, aber nicht per se unterstützt)

  • PHP Version 8.0

  • Benötigte folgende PHP Erweiterungen:

    • cURL

    • GD

    • ImageMagick

    • JSON-Support

    • mbstring

    • MySQLi

    • Socket-Support

    • SPL

  • eingesetztes Template

    • NOVA

    • easyTemplate

    • andere Templates müssen ggf. mit Servicepartner geprüft werden

Weitere Voraussetzungen

Sie müssen bei Clerk.io registriert sein, um einen API Schlüssel zu erhalten.

Plugin-Installation

Die Installation des Plugins erfolgt im Standardverfahren für JTL-Shop 5, wie es hier beschrieben ist.

Plugin-Update

Für ein Update laden Sie das Plugin wie bei einer Installation in der neuesten Version hoch (und überschreiben ggf. alle vorhandenen Plugin Dateien) oder folgen Sie den Hinweisen des Extension Stores.

Gehen Sie dann in die Plugin Verwaltung und betätigen Sie den Update-Button.

Konfiguration (Shop)

Einstellungen des Plugins

Die Einstellungen des Plugins erreichen Sie über Plugins → Installierte Plugins → S360 Clerk → Einstellung

 

Bereich

Option

Bedeutung

Bereich

Option

Bedeutung

Allgemein

Cookieless Tracking nutzen

Tracking ohne Cookie Nutzung

 

Warenkorb Tracking nutzen?

Informiert Clerk über Änderungen am Warenkorb (allg. Tracking des Warenkorbs)

 

E-Mails anonymisieren

E-Mail Adressen werden anonymisiert (als Hash) an Clerk übertragen

 

 

 

Live Suche (Header)

Live Suche aktivieren?

Falls deaktiviert wird im Frontend die Clerk Live Suche nicht ausgespielt.

 

Selektor Livesuche

Selektor für die Live-Suche unabhängig von Clerk

 

Clerk TemplateName Livesuche

Template für die Live-Suche (Clerk Backend → Search → Content → Livesuche → Insert into website → Im Code den Wert aus “data-template=”@WERT'“)

 

Anzahl Suchvorschläge in der Livesuche

Anzahl der Suchvorschläge die angezeigt werden soll

 

Anzahl Kategorievorschläge

Anzahl der Kategorie Vorschläge die angezeigt werden soll

 

Anzahl Seitenvorschläge

Anzahl der Seitenvorschläge die angezeigt werden soll

 

Position

Position des Live-Suche Ergebnisses in Bezug auf den Selektor

 

 

 

Suche (Ergebnisseite)

Ergebnisseite aktivieren?

Falls deaktiviert wird im Frontend die Clerk Ergebnisseite nicht ausgespielt.

 

Clerk TemplateName Suche

Template für die Live-Suche (Clerk Backend → Search → Content → Suche → Insert into website → Im Code den Wert aus “data-template=”@WERT'“)

 

Position Facetten

Position der Facetten

 

Facetten in URL anzeigen

Facetten in URL anzeigen

 

Clerk Facetten Attribute

Kommagetrennte Liste der verfügbaren Facetten (JTL Merkmale)

 

Clerk Facetten Attribute Multiple Werte

Kommagetrennte Liste der verfügbaren Facetten mit multiplen Werten (JTL Merkmale für ODER Filterung)

 

Bereich

Option

Bedeutung

Bereich

Option

Bedeutung

Data Feed

Cronverarbeitung

Art und Weise wie der Cron zur Generierung des Daten Feeds angestoßen werden soll (Im Abschnitt Möglichkeiten der Daten Feed Erstellung genauer erklärt)

 

Stapelgröße

Stapelgröße der Produkte des Feeds (Im Abschnitt Stapelgröße genauer erklärt)

 

 

 

Produkt Seite

Produktseiten Slider aktivieren?

Falls deaktiviert wird im Frontend der Slider auf der Produktseite nicht ausgespielt.

 

Artikel Selektor Slider

Selektor für den Artikel Slider unabhängig von Clerk

 

Clerk TemplateName Artikel

Namen der Slider Templates die ausgegeben werden sollen. Mehrere Template Namen können als komma-separierte Liste angegeben werden.

 

Slider

Einfügemethode, wie der Slider zum Selektor hinzugefügt werden soll (After, Append, Before, Prepand, ReplaceWith)

 

Duplikate filtern

Verhindert, dass nachfolgende Slider Produkte aus vorherigen Slidern enthalten (Standard: Ja)

 

 

 

Warenkorb Seite

Warenkorb Slider aktivieren?

Falls deaktiviert wird im Frontend der Slider auf der Warenkorbseite nicht ausgespielt.

 

Warenkorb Selektor Slider

Selektor für den Warenkorb Slider unabhängig von Clerk

 

Clerk TemplateName Warenkorb

Namen der Slider Templates die ausgegeben werden sollen. Mehrere Template Namen können als komma-separierte Liste angegeben werden.

 

Slider

Einfügemethode, wie der Slider zum Selektor hinzugefügt werden soll (After, Append, Before, Prepand, ReplaceWith)

 

Duplikate filtern

Verhindert, dass nachfolgende Slider Produkte aus vorherigen Slidern enthalten (Standard: Ja)

 

 

 

Powerstep

Powerstep Slider aktivieren?

Falls deaktiviert wird im Frontend der Slider im Powerstep nicht ausgespielt.

 

Powerstep Selektor

Selektor für den Powerstep Slider unabhängig von Clerk

 

Clerk TemplateName Powerstep

Namen der Slider Templates die ausgegeben werden sollen. Mehrere Template Namen können als komma-separierte Liste angegeben werden.

 

Powerstep Einfügemethode

Einfügemethode, wie der Slider zum Selektor hinzugefügt werden soll (After, Append, Before, Prepand, ReplaceWith)

 

Duplikate filtern

Verhindert, dass nachfolgende Slider Produkte aus vorherigen Slidern enthalten (Standard: Ja)

 

Bereich

Option

Bedeutung

Bereich

Option

Bedeutung

Kategorie Seite

Kategorieseiten Slider aktivieren?

Falls deaktiviert wird im Frontend der Slider auf der Kategorieseite nicht ausgespielt.

 

Kategorie Selektor Slider

Selektor für den Kategorie Slider unabhängig von Clerk

 

Clerk TemplateName Warenkorb

Namen der Slider Templates die ausgegeben werden sollen. Mehrere Template Namen können als komma-separierte Liste angegeben werden.

 

Slider

Einfügemethode, wie der Slider zum Selektor hinzugefügt werden soll (After, Append, Before, Prepand, ReplaceWith)

 

Duplikate filtern

Verhindert, dass nachfolgende Slider Produkte aus vorherigen Slidern enthalten (Standard: Ja)

 

 

 

Exit Intent (Ausstiegsabsicht)

Exit Intent Slider aktivieren?

Falls deaktiviert wird im Frontend der Exit Intent nicht ausgespielt.

 

Clerk TemplateName Exit Intent

Template für den Exit Intent

 

Erstellung von Datenfeeds

Einstellungen:

Die Einstellungen des Datenfeeds erreichen Sie über Plugins → Installierte Plugins → S360 Clerk → klick auf Zahnrad (siehe Bild)

Hier kann genau ausgewählt werden, welche Daten dem Feed hinzugefügt werden bzw. welche für Sie relevant sind.

 

Option

Bedeutung

Option

Bedeutung

API Key

Ihr von Clerk erhaltener API Schlüssel

Private Key

Ihr von Clerk bereitgestellter Legacy private API Key. Wird für die Zugriffsbeschränkung auf den Daten-Feed benötigt.

Sprache

Sprache des Daten Feeds

Kundengruppe

Preise für die Kundengruppe

Währung

Währung im Daten Feed

Facetten Design

Design der Facetten

Weitere Informationen sind aus der jeweiligen Reihe zu entnehmen (i-Icon).

Weitere Daten Feed Einstellungen

Möglichkeiten der Daten Feed Erstellung

Es gibt 3 Möglichkeiten die Generierung der Cron-Jobs anzustoßen:

  1. CLI → Bei CLI wird der Cronjob über den Shop CLI Befehl php cli s360_clerk_shop5:cron aufgerufen

  2. Wawi Abgleich → Cronjob wird beim Wawi Abgleich mit ausgeführt

  3. Aufgabenplaner → Der Cronjob wird zusammen mit anderen Cronjobs z.B Exporte über den Aufruf der cron_inc.php angestoßen. (Standard JTL Cron → JTL5-Shop Backend -> System-> Cron)

Gesamtablauf zur Erstellung des Feeds

  1. Feed im Shop Backend einstellen (Plugins → Installierte Plugins → S360 Clerk → klick auf Zahnrad (siehe Bild))

  2. Nach den Einstellungen, den Feed erstellen (Plugins → Installierte Plugins → S360 Clerk → klick auf Doppelpfeil)

  3. Nach erfolgreichem erstellen muss der Feed im Clerk.io Backend hinterlegt werden:

 

Stapelgröße

Anstatt alle Produkte auf einmal aus der Datenbank auszulesen, wird immer nur ein Stapel von Produkten auf einmal ausgelesen .

Bei einer großen Anzahl an Produkten, kann so der Speicherverbrauch stark reduziert werden., erhöht dabei allerdings die Laufzeit.

Ist der Wert auf 0 gesetzt, werden ALLE Produkte ausgegeben.

Konfiguration Shop bei Clerk.io (Allgemein)

Das Standardisierte Vorgehen zum hinzufügen neuer Elemente ist:

  1. Öffnen des Clerk.io Backends

  2. Design erstellen

  3. Content hinzufügen

  4. Einstellungen im Plugin Backend

Hinzufügen des Warenkorb-Sliders

Neue Slider können via Clerk Backend erzeugt und hinzugefügt werden.

Anlegen des Design erfolgt im Clerk.io Backend unter Recommendations → Designs.

Hier kann via HTML und CSS das Grund-Design angepasst werden.

Wichtig: Lieferstatus wird momentan nur vom EasyTemplate Slider unterstützt.

Vorlage Design Nova:

{% if products.length != 0 %} <div class="slick-slider-other is-not-opc"> <div class="hr-sect h2"> {{ headline }} </div> <div id="slick-slider-{{ snippets.settings.slider.id }}" class="carousel-arrows-inside carousel slick-smooth-loading slider-no-preview slick-type-product slick-lazy" data-slick-type="product-slider"> {% for product in products %} <div class="product-wrapper col"> <div id="result-wrapper_buy_form_{{ product.id }}" data-wrapper="true" class="productbox productbox-column"> <div class="productbox-inner"> <div class="row"> <div class="col col-12"> <div class="productbox-image"> <div class="productbox-images"> <a href="{{ product.url }}" title="{{ product.name }}"> <div class="productbox-image square square-image"> <div class="inner"> <picture> <img src="{{ product.image }}" class="img-fluid" loading="lazy" alt="{{ product.name }}" /> </picture> </div> </div> {% if product.top_article and product.top_article != false %} <div class="ribbon ribbon-4 productbox-ribbon"> {{ snippets.ribbons.4 }} </div> {% endif %} {% if product.on_sale and product.on_sale != false %} <div class="ribbon ribbon-2 productbox-ribbon"> {{ snippets.ribbons.2 }} </div> {% endif %} {% if product.in_stock and product.in_stock != false %} <div class="ribbon ribbon-8 productbox-ribbon"> {{ snippets.ribbons.8 }} </div> {% endif %} {% if product.in_stock and product.in_stock <= 0 %} <div class="ribbon ribbon-7 productbox-ribbon"> {{ snippets.ribbons.7 }} </div> {% endif %} {% if product.age and product.age <= snippets.settings.newProductmaxDays %} <div class="ribbon ribbon-3 productbox-ribbon"> {{ snippets.ribbons.3 }} </div> {% endif %} {% if product.average_rating and product.average_rating <= snippets.settings.topProductMinStars %} <div class="ribbon ribbon-6 productbox-ribbon"> {{ snippets.ribbons.6 }} </div> {% endif %} {% if product.age and product.age < 0 %} <div class="ribbon ribbon-5 productbox-ribbon"> {{ snippets.ribbons.5 }} </div> {% endif %} {% if product.vorbestellbardate and product.vorbestellbardate > 0 %} <div class="ribbon ribbon-9 productbox-ribbon"> {{ snippets.ribbons.9 }} </div> {% endif %} {% if product.age and product.age > 0 and product.stock <= 0 %} <div class="ribbon ribbon-5 productbox-ribbon"> {{ snippets.ribbons.5 }} </div> {% endif %} </a> </div> </div> </div> <div class="col col-12"> <div class="productbox-title"> <a href="{{ product.url }}" title="{{ product.name }}" class="text-clamp-2"> {{ product.name }} </a> </div> {% if product.reviews_avg > 0 %} <a class="rating" href="{{ product.url }}#tab-votes" title="{{ snippets.productRating }}: {{ product.reviews_avg }}/5"> {% if product.reviews_avg >= 5 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i> {% else %} {% if product.reviews_avg >= 4 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.reviews_avg > 4 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %} {% else %} {% if product.reviews_avg >= 3 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.reviews_avg > 3 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.reviews_avg >= 2 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.reviews_avg > 2 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.reviews_avg >= 1 %} <i class="{{ snippets.icons.rating }}"></i>{% if product.reviews_avg > 1 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.reviews_avg > 0 %} <i class="{{ snippets.icons.ratingHalf }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% endif %} {% endif %} {% endif %} {% endif %} {% endif %} {% endif %} </a> {% else %} <div class="rating productbox-rating-empty"></div> {% endif %} <div> <div class="price_wrapper"> {% if product.has_variations or product.bulk_prices != 0 %} <span class="price_label pricestarting"> {{ snippets.priceStarting }} </span> {% endif %} <div class="price productbox-price {% if product.on_sale %} special-price{% endif %}"> <span>{{ product.price | money_eu }} {{ globals.currency_symbol }} <span class="footnote-reference">*</span></span> </div> {% if product.on_sale %} <div class="price-note"> <div class="instead-of old-price"> <small class="text-muted-util"> <del class="value">{{ product.original_price | money_eu }} {{ globals.currency_symbol }}</del> </small> </div> </div> {% endif %} {% if product.base_price > 0 %} <div class="price-note"> <span class="value">{{ product.base_price | money_eu }} {{ globals.currency_symbol }} {{ snippets.vpePer }} {{ product.base_price_unit }}</span> </div> {% else %} <div class="price-note">&nbsp;</div> {% endif %} </div> </div> </div> </div> </div> </div> </div> {% endfor %} </div> </div> <script> $(function() { $.evo.generateSlickSlider(); $.evo.popover(); }); </script> {% endif %}

Vorlage Design EasyTemplate:

{% if products.length != 0 %} <div class="et-widget-clerkslider-headline"> <div class="et-product-slider-headline"> <div class="et-textfield text-align-default et-widget-headline h2">{{ headline }}</div> </div> </div> <div class="et-product-slider-wrapper row"> <div class="col p-0"> <div class="slick-slider-other is-not-opc"> <div id="et-clerk-slider-{{ snippets.settings.slider.id }}" class="et-product-slider-slider et-slider carousel slick-smooth-loading slider-no-preview slick-type-product"> {% for product in products %} <div class="product-wrapper col"> <div id="result-wrapper_buy_form_{{ product.id }}" data-wrapper="true" class="productbox productbox-show-variations et-item-box productbox-column"> <div class="productbox-inner"> <div class="row"> <div class="col col-12"> <div class="productbox-image"> {% if product.top_article and product.top_article != false %} <div class="ribbon ribbon-4 productbox-ribbon"> {{ snippets.ribbons.4 }} </div> {% endif %} {% if product.on_sale and product.on_sale != false %} <div class="ribbon ribbon-2 productbox-ribbon"> {{ snippets.ribbons.2 }} </div> {% endif %} {% if product.in_stock and product.in_stock != false %} <div class="ribbon ribbon-8 productbox-ribbon"> {{ snippets.ribbons.8 }} </div> {% endif %} {% if product.in_stock and product.in_stock <= 0 %} <div class="ribbon ribbon-7 productbox-ribbon"> {{ snippets.ribbons.7 }} </div> {% endif %} {% if product.age and product.age <= snippets.settings.newProductmaxDays %} <div class="ribbon ribbon-3 productbox-ribbon"> {{ snippets.ribbons.3 }} </div> {% endif %} {% if product.average_rating and product.average_rating <= snippets.settings.topProductMinStars %} <div class="ribbon ribbon-6 productbox-ribbon"> {{ snippets.ribbons.6 }} </div> {% endif %} {% if product.age and product.age < 0 %} <div class="ribbon ribbon-5 productbox-ribbon"> {{ snippets.ribbons.5 }} </div> {% endif %} {% if product.vorbestellbardate and product.vorbestellbardate > 0 %} <div class="ribbon ribbon-9 productbox-ribbon"> {{ snippets.ribbons.9 }} </div> {% endif %} {% if product.age and product.age > 0 and product.stock <= 0 %} <div class="ribbon ribbon-5 productbox-ribbon"> {{ snippets.ribbons.5 }} </div> {% endif %} <div class="productbox-images list-gallery"> <a href="{{ product.url }}" title="{{ product.name }}"> <div class="productbox-image square square-image"> <div class="inner"> <picture> <img src="{{ product.image }}" class="img-fluid" loading="lazy" alt="{{ product.name }}" /> </picture> </div> </div> </a> </div> </div> </div> <div class="col col-12"> <div class="productbox-caption"> <div class="et-item-box-manufacturer productbox-manufacturer"> <span>{% if snippets.settings.showBrand %}{{ product.brand }}{% endif %}</span> </div> <div class="et-item-box-title productbox-title"> <a href="{{ product.url }}" class="text-clamp-2 link-discreet"> {{ product.name }} </a> </div> <div class="et-item-box-rating productbox-rating"> {% if product.average_rating > 0 %} <a class="rating" href="{{ product.url }}#tab-votes" title="{{ snippets.productRating }}: {{ product.average_rating }}/5"> {% if product.average_rating >= 5 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i> {% else %} {% if product.average_rating >= 4 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.average_rating > 4 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %} {% else %} {% if product.average_rating >= 3 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.average_rating > 3 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.average_rating >= 2 %} <i class="{{ snippets.icons.rating }}"></i><i class="{{ snippets.icons.rating }}"></i>{% if product.average_rating > 2 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.average_rating >= 1 %} <i class="{{ snippets.icons.rating }}"></i>{% if product.average_rating > 1 %}<i class="{{ snippets.icons.ratingHalf }}"></i>{% else %}<i class="{{ snippets.icons.ratingEmpty }}"></i>{% endif %}<i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% else %} {% if product.average_rating > 0 %} <i class="{{ snippets.icons.ratingHalf }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i><i class="{{ snippets.icons.ratingEmpty }}"></i> {% endif %} {% endif %} {% endif %} {% endif %} {% endif %} {% endif %} </a> {% endif %} </div> {% if product.in_stock %} {% if product.stock >= snippets.settings.storageLightsGreen%} <div class="delivery-status"> <ul class="list-unstyled"> <li> <span class="status status-2"> <span class="{{snippets.settings.storageLightIcon}} status-icon"> </span> <span class="status-text">{{snippets.settings.storageLightTextGreen}}</span> </span> </li> </ul> </div> {% endif %} {% if product.stock > snippets.settings.storageLightsRed and product.stock < snippets.settings.storageLightsGreen %} <div class="delivery-status"> <ul class="list-unstyled"> <li> <span class="status status-1"> <span class="{{snippets.settings.storageLightIcon}} status-icon"> </span> <span class="status-text">{{snippets.settings.storageLightTextYellow}}</span> </span> </li> </ul> </div> {% endif %} {% if product.stock == snippets.settings.storageLightsRed%} <div class="delivery-status"> <ul class="list-unstyled"> <li> <span class="status status-0"> <span class="{{snippets.settings.storageLightIcon}} status-icon"> </span> <span class="status-text">{{snippets.settings.storageLightTextRed}}</span> </span> </li> </ul> </div> {% endif %} {% endif %} <div class="et-item-box-price"> <div class="price_wrapper"> {% if product.has_variations or product.bulk_prices != 0 %} <span class="price_label pricestarting"> {{ snippets.priceStarting }} </span> {% endif %} <div class="price productbox-price {% if product.on_sale %} special-price{% endif %}"> <span>{{ product.price | money }} {{ globals.currency_symbol }} <span class="footnote-reference">*</span></span> </div> {% if product.on_sale %} <div class="price-note et-old-price"> <div class="instead-of old-price"> <small class="text-muted-util"> <del class="value">{{ product.original_price | money }} {{ globals.currency_symbol }}</del> </small> </div> </div> {% endif %} {% if product.base_price > 0 %} <div class="price-note"> <span class="value">{{ product.base_price | money }} {{ globals.currency_symbol }} {{ snippets.vpePer }} {{ product.base_price_unit }}</span> </div> {% else %} <div class="price-note">&nbsp;</div> {% endif %} </div> </div> </div> </div> </div> </div> </div> </div> {% endfor %} </div> <div class="et-slider-nav" id="clerk-slider-nav-{{ snippets.settings.slider.id }}"> <div class="et-slider-nav-prev enabled slick-arrow slick-hidden" id="clerk-slider-prev-{{ snippets.settings.slider.id }}"> <i class="{{ snippets.icons.sliderPrevious }}"></i> </div> <div class="et-slider-nav-next enabled slick-arrow slick-hidden" id="clerk-slider-next-{{ snippets.settings.slider.id }}"> <i class="{{ snippets.icons.sliderNext }}"></i> </div> </div> </div> </div> </div> <script> $(function() { $("#et-clerk-slider-{{ snippets.settings.slider.id }}").slick({{ snippets.settings.slider.settings }}); $.evo.popover(); }); </script> {% endif %}

Content hinzufügen

Unter Clerk.io → Recommendations → Content , kann der Content für den neuen Warenkorb-Slider erzeugt werden (Button New Content)

 

Die nun folgende Seite beinhaltet 4 wichtige Abschnitte:

  1. Name your content → Hier wird der Name festgelegt

  2. Choose product logic → Hier kann die Produktlogik ausgewählt werden, unter anderem “Best Sellers” / “Hot Products” und vieles mehr

  3. Select design → Welches Design soll verwendet werden / wie soll die Überschrift lauten und wie viele Produkte sollen angezeigt werden (Wichtig: wird durch das Plugin festgelegt, auch wenn hier eine “Anzahl” hinterlegt werden kann)

  4. Insert into website → Hier wird der Name ausgegeben, den wir in unserem JTL5-Shop Backend unter Clerk TemplateName Warenkorb eingeben müssen

Nachdem alles eingestellt und befüllt wurde, muss nun ins JTL5-Shop Backend gewechselt werden und dort wird nun der Name der Komponente (aus Insert into website) hinterlegt.

Einstellung Plugin Backend

Hinzufügen des Artikel Sliders

Das Hinzufügen des Artikel Sliders verläuft äquivalent zum Warenkorb Slider.

Es werden im Standardfall, die selben Design Dateien verwendet (Slider NOVA / Slider ET), lediglich der Name/Produktlogik im Clerk.io Backend wird verändert und im Plugin Backend wird ein anderer Selektor gewählt.

Hinzufügen der Live-Suche

Verläuft äquivalent zu den Slidern:

  • Design erstellen

  • Content hinzufügen

  • Einstellungen im Plugin Backend

Anlegen des Design erfolgt im Clerk.io Backend unter Search → Designs.

Unterschiede zu den Slidern:

  • Hier wird auch der CSS Abschnitt befüllt.

  • Kein Unterschied zwischen Nova und EasyTemplate Design

Design:

HTML Datei:

<div id="clerk-template-live-search" style="background: white"> <div class="clerk-live-search"> <div class="row"> <div class="col-12 col-sm-8 clerk-live-search-products"> {% if products.length != 0 %} <div class="h4 headline-style">{{ snippets.headlineProducts }}</div> {% for product in products %} <div class="product clerk-instant-search-key-selectable"> <a href="{{ product.url }}" class="d-block product-link link-discreet"> <div class="row align-items-center"> <div class="col-2 text-center product-image-wrapper"> <img src="{{ product.image }}" class="product-image img-fluid" /> </div> <div class="col-7"> <div class="product-name productbox-title et-mb-0">{{ product.name }}</div> </div> <div class="col-3"> <div class="price_wrapper text-right"> {% if product.has_variations or product.bulk_prices != 0 %} <span class="price_label pricestarting"> {{ snippets.priceStarting }} </span> {% endif %} {% if product.on_sale %} <span class="instead-of old-price"> <small class="text-muted-util"> <del class="value">{{ product.original_price | money_eu }} {{ globals.currency_symbol }}</del> </small> </span> {% endif %} <span class="price productbox-price {% if product.on_sale %} special-price{% endif %}"> <span>{{ product.price | money_eu }} {{ globals.currency_symbol }} <span class="footnote-reference">*</span></span> </span> {% if product.base_price > 0 %} <div class="price-note"> <span class="value">{{ product.base_price | money_eu }} {{ globals.currency_symbol }} {{ snippets.vpePer }} {{ product.base_price_unit }}</span> </div> {% endif %} </div> </div> </div> </a> </div> {% endfor %} <div class="text-center"> <a href="{{ snippets.searchUrl }}?query={{ query }}" class="btn btn-secondary btn-lg"> {{ snippets.showAllResults }} </a> </div> {% else %} <div class="text-center"> {{ snippets.textNoResults | replace '###QUERY###' query | highlight query 'clerk-live-search-highlight' }} </div> {% endif %} </div> <div class="col col-sm-4 clerk-live-search-others"> {% if suggestions.length != 0 %} <div class="h4 headline-style">{{ snippets.headlineSuggestions }}</div> <div class="clerk-live-search-others-wrapper clerk-suggestion"> {% for suggestion in suggestions %} <a href="{{ snippets.searchUrl }}?query={{ suggestion }}"> {{ suggestion }} </a> {% endfor %} </div> {% endif %} {% if categories.length != 0 %} <div class="h4 headline-style">{{ snippets.headlineCategories }}</div> <div class="clerk-live-search-others-wrapper clerk-category"> {% for category in categories %} <a href="{{ category.url }}"> {{ category.name }} </a> {% endfor %} </div> {% endif %} {% if pages.length != 0 %} <div class="h4 headline-style">{{ snippets.headlinePages }}</div> <div class="clerk-live-search-others-wrapper clerk-pages"> {% for page in pages %} <a href="{{ page.url }}"> {{ page.title }} </a> {% endfor %} </div> {% endif %} </div> </div> </div> </div>

CSS Datei:

Content:

Hinzufügen der Facetten

  • Design erstellen in Clerk (Clerk.io Backend unter Search → Designs)

  • Nach der Erstellung wird eine ID, diese muss im Plugin Backend(Plugins → Installierte Plugins → S360 Clerk → klick auf Zahnrad → Einstellungen → Facetten Design) hinterlegt werden

 

Vorlage Design Nova:

Vorlage Design EasyTemplate:

Hinzufügen der Suchergebnisse

Verläuft äquivalent zu den Slidern:

  • Design erstellen

  • Content hinzufügen

  • Einstellungen im Plugin Backend

Anlegen des Design erfolgt im Clerk.io Backend unter Search → Designs.

Vorlage Design Nova:

Vorlage Design EasyTemplate:

Eigene zusätzliche Slider hinzufügen

EasyTemplate

Im EasyTemplate können eigene Slider leicht mit folgenden Schritte integriert werden:

  1. Erstellung des Design im Clerk.io Backend (es können auch bereits vorhandene Designs verwendet werden)

 

2. Erstellung des Contents mit dem jeweiligen Fokus in Clerk.io , kopieren des nötigen Span Elements

 

3. Hinzufügen eines HTML Widgets im EasyTemplate

4. Einfügen des Element in einen HTML Widget im EasyTemplate.

Wichtig dabei ist die Zeile data-snippets='{json_encode($s360_clerk_snippets->get())}' zu dem Clerk HTML Schnipsel aus Schritt 2 hinzuzufügen, damit die Sprachvariablen korrekt an Clerk übergeben werden! Außerdem muss der Haken bei “Smarty evaluieren gesetzt werden”

OnPage Composer

Im OnPage Composer können eigene Slider mit folgenden Schritte integriert werden:

1. Erstellung des Design im Clerk.io Backend (es können auch bereits vorhandene Designs verwendet werden)

 

2. Erstellung des Contents mit dem jeweiligen Fokus in Clerk.io , kopieren des nötigen Span Elements

3. Öffnen des OnPage Composer

4. Neuer Entwurf im OnPage Composer

5. Rich Text Element per Drag&Drop im Onpage Composer auf die gewünschte ziehen → Quellcode im Menü auswählen und das kopierte Span Elemente hier hinzufügen

6. Speichern → Veröffentlichen mit Zeitraum auswählen

 

Anmerkung: Je nach Position des “eigenen Sliders”, müssen auch weitere CSS Eigenschaften/Klassen ergänzt werden, wenn nicht das Standard Template verwendet wird.

PHP Events

Das Plugin bietet JTL5_shop Hooks an (https://jtl-devguide.readthedocs.io/projects/jtl-shop/de/latest/shop_plugins/hook_list.html ).

Name

Parameter

Beschreibung

Name

Parameter

Beschreibung

s360_clerk_shop5.get_sales_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\InitialOrderFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_sales_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\InitialOrderFeedBuilder builder

  • Aufruf bevor eine Bestellung in den Feed aufgenommen wird

  • Eigenschaften der Bestellung können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.get_pages_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\PageFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_pages_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\PageFeedBuilder builder

  • Aufruf bevor eine eigene Seite in den Feed aufgenommen wird

  • Eigenschaften der eigene Seite können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.get_blog_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\BlogFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_blog_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\BlogFeedBuilder builder

  • Aufruf bevor ein Blog in den Feed aufgenommen wird

  • Eigenschaften des Blogs können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.get_customers_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\CustomerFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_customers_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\CustomerFeedBuilder builder

  • Aufruf bevor ein Kunde in den Feed aufgenommen wird

  • Eigenschaften des Kunden können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.get_categories_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\CategoryFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_categories_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\CategoryFeedBuilder builder

  • Aufruf bevor eine Kategorie in den Feed aufgenommen wird

  • Eigenschaften der Kategorie können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.get_product_query

string &$query

\Plugin\s360_clerk_shop5\src\Export\ProductFeedBuilder builder

  • Beziehen der Datenbankabfrage

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.process_product_row

array &$row

\Plugin\s360_clerk_shop5\src\Export\ProductFeedBuilder builder

  • Aufruf bevor ein Produkt in den Feed aufgenommen wird

  • Eigenschaften des Produkts können bearbeitet werden (z.B. zusätzliche Eigenschaften hinzufügen)

s360_clerk_shop5.boot_product_feed_builder

\Plugin\s360_clerk_shop5\src\Export\ProductFeedBuilder builder

  • Aufruf bevor ein Produkt in den Feed aufgenommen wird → Boot Methode für das Produkt

  • Hier können Attribute/Charakteristiken sowie Einstellungen verändert werden

s360_clerk_shop5.get_product_bulk_price_query

array &$row

\Plugin\s360_clerk_shop5\src\Export\ProductFeedBuilder builder

  • Beziehen der Datenbankabfrage für den Mengenpreis

  • Hier kann das SQL Query angepasst werden (weitere Felder hinzufügen, Sortierung ändern)

s360_clerk_shop5.boot_specific_feed_builder

\Plugin\s360_clerk_shop5\src\Export\AbstractFeedBuilder builder

  • Boot Methode für alle von AbstractFeedBuilder extendenden Klassen

Individualisierung

Die Individualisierung erfolgt über Dateiname_custom, somit kann die jeweilige .tpl Datei erweitert werden (Bsp.: clerk_article_custom.tpl)

Pfad im Plugin

Verwendungszweck

Pfad im Plugin

Verwendungszweck

frontend/template/clerk_article.tpl

Enthält das Template und API Parameter um die Produkt darzustellen.

frontend/template/clerk_category.tpl

Enthält das Template und API Parameter um die Kategorie Slider darzustellen.

frontend/template/clerk_live_search.tpl

Enthält die wichtigsten Parameter und JS um die Live-Suche darzustellen.

frontend/template/clerk_config.tpl

Enthält die nötigen JS und Clerk Konfigurationen inklusive Cookieless Tracking / API-Key

frontend/template/clerk_sales_tracking.tpl

Enthält das Template um den Verkaufsverlauf darzustellen.

frontend/template/clerk_searchresults.tpl

Enthält die Wichtigsten JS Sachen und API-Parameter um die Suchergebnisse darstellen zu können.

frontend/template/clerk_shopping_cart.tpl

Enthält das Template + API Parameter für den Warenkorb.

Formatierungen

Standardformatierung money_eu:

  • Formatiert eine Dezimalzahl als Währung unter Verwendung der EU-Formatierungsregeln

Auch möglich money:

  • Formatiert eine Dezimalzahl als Währung unter Verwendung der US-Formatierungsregeln

Zusätzlich sind auch eigene Formatierungen möglich:

Troubleshooting

Sollten Sie Probleme mit dem Plugin beobachten, prüfen Sie zunächst die Logs und wenden Sie sich ggf. an unseren Support oder Ihren Service-Partner, wenn Sie das Problem nicht selbständig lösen können.

Je mehr Informationen Sie dem Support bei einem Problem geben können, desto eher sind wir in der Lage, Ihnen zu helfen. Nicht reproduzierbare Probleme sind dagegen auch nur schwer zu analysieren.

Logs prüfen

Um herauszufinden, wo ein Problem liegt, helfen Ihnen und uns die Logs. Je nach Fehlerbild ist eines der folgenden 3 Logs dafür mehr oder weniger relevant.

Browser-Log

Das Browser-Log ist meist relevant, wenn irgendwas im Frontend des Shops sich merkwürdig verhält oder nicht reagiert. (Beispiel: Sie klicken einen Button und augenscheinlich passiert gar nichts.)

Das Browser-Log sehen Sie, wenn Sie im Browser F12 drücken und dort dann auf Konsole (oder Console) wechseln.

Shop-Log

Das Shop-Log ist immer dann interessant, wenn im Frontend unerwartete Fehlermeldungen ausgegeben werden oder das Plugin zwar auf Eingaben im Frontend reagiert, aber nicht das Ergebnis liefert, was erwartet wurde. Manchmal ergibt sich auch durch das Browser-Log, dass die Informationen eher im Shop-Log zu suchen sind.

Das Shop-Log finden Sie im JTL-Adminbereich unter Administration→ Fehlerbehebung → Logbuch.

Das JTL-Log arbeitet mit Log-Levels, um nicht die Datenbank unbegrenzt mit Logdaten zu befüllen. Im Umkehrschluss heißt das, dass Sie Logmeldungen aber auch erst dann sehen, wenn diese nach der Änderung des Loglevels erzeugt worden sind.
Das Plugin loggt außer kritischer Fehler fast ausschließlich im Debug-Log-Level. Wenn also etwas nicht klappt, sollten Sie zunächst das Debug-Loglevel aktivieren, dann eine Testbestellung durchführen, dann das Debug-Loglevel wieder deaktivieren und die zwischenzeitlich geloggten Meldungen zurate ziehen.

Webserver-Log

Das Webserver-Log wird dann relevant, wenn Sie irgendwo auf einen Error 500 (= weiße Seite) stoßen.

Das Webserver-Log kann Ihnen Ihr Hoster zur Verfügung stellen.

In der Standardkonfiguration loggt der JTL-Shop überhaupt nichts in das Webserverlog, nicht mal kritische Fehler wie einen Error 500.

Damit der Shop diese Fehler loggt, müssen in der /includes/config.JTL-Shop.ini.php die einzelnen *_LOG_LEVEL Werte von 0 auf E_ERROR geändert werden.

Achtung: Editieren Sie die Config-Datei des Shops nur, wenn Sie wissen, was Sie tun! Fehlerhafte Anpassungen hier können Ihren Shop unerreichbar oder (verschlüsselte) Daten unbrauchbar machen. Im Zweifelsfall sollten Sie Ihren Hoster oder Servicepartner um Hilfe fragen.

FAQ

Ein Slider wurde hinzugefügt, wird aber nicht angezeigt?

  1. Der Selektor wurde falsch gewählt → Lösung: Ein andere Selektor zum einbinden des Plugins/Elements sollte gewählt werden.

  2. Das Slider Einfügemethode ist falsch → Lösung: Meist reicht hier schon die Einfügemethode selbst zu verändern im JTL5-Shop Backend

Der Exporter funktioniert nicht, was tun?

  1. Der Exporter braucht Schreibrechte, da dieser ohne sonst nicht agieren kann.

Die Suche zeigt keine/falsche Ergebnisse?

  1. Prüfen. ob ein Api-Key hinterlegt wurde

  2. Bei mehreren Shops prüfen, ob der richtige Api-Key hinterlegt wurde.

Changelog

v1.0.4 (November 2023)

  • Added: Einstellungen um einzelne Bereiche im Frontend zu aktivieren/deaktivieren hinzugefügt

  • Added: Einstellungen um Slider auf der Kategorie-Seite anzuzeigen

  • Changed: Export der Bestellungen nimmt jetzt ALLE Bestellungen in den Feed auf und nicht nur die letzten 1000

  • Fix: Kategorie-Rabatte werden jetzt im Export mit berücksichtigt

v1.0.3 (Oktober 2023)

  • Fix: Nutzen der Standard JTL Bildpfad-Logik im Export-Feed

v1.0.2 (September 2023)

  • Fix: Leere PQ Selektoren verursachen Fehlerlogs

  • Fix: MySQL GROUP_CONCAT kann bei großen Abfragen zu abgeschnittenen Ergebnissen führen

  • Removed: Template Kopien aus der Clerk Plugin-Dokumentation entfernt

v1.0.1 (September 2023)

  • Fix: Leere Produkt-IDs im Order Feed führen zu einem Fehler im Clerk Sync, stattdessen wird nun als ID -1 genutzt

  • Fix: Facetten mit Umlauten funktionieren nicht

  • Change: Benutzen von cBestellNr anstatt kBestellung als ID im Order Feed

v1.0.0 (August 2023)

  • Added: Berücksichtigung der Shop Einstellung "Kategorieanzeige" (ID 115) = "Leere Kategorien ausblenden"

  • Fix: Sonderpreis wird angezeigt obwohl Sonderpreis nicht aktiv

  • Fix: "has_variations" Attribut im Produkt-Export ist immer false

Support und Kontakt

siehe Support und Kontakt