Breezing Forms: ein kurzer theoretischer Durchlauf

Theoretisch deswegen, weil Breezing Forms nicht mit meinem Xampp-Mailtodisk zusammenarbeitet und ich den Output nicht kontrollieren kann. Trotzdem, packma’s und schauen uns den populärsten Formulareditor für Joomla mal näher an.

Installation

Erweiterungen->Webkatalog->Breezing Forms free suchen und installieren, dann unter Komponenten->Breezing Forms die Installation vervollständigen.

Neues Formular anlegen

Unter Formulare verwalten->Neu kommt man in einen Formulareditor, und hier wirds schwer gewöhnungsbedürftig. Zuerst mal einen Titel (freie Zeichenwahl) und einen Namen (nur alphanumerisch) für das neue Formular vergeben. Dann muss man erstmal eine Seite hinzufügen, das geht mit Klick auf den „Page“-Button. Mit einem Klick auf „Element“ kann man der eben erstellten Seite 1 Formularfelder hinzufügen, die Optionen sind recht selbsterklärend. Ich belasse es mal bei einem Feld für den Namen des Absenders und einer Textarea für die Nachricht. Anschauen kann man sich das Ganze dann unter „Vorschau“. Das ist alles ziemlich unhandlich und wenig intuitiv, aber mit ein bisschen Übung wird das schon.

Neuen Menüpunkt für das Formular erstellen

Menüs->Main Menu (oder wie es bei ihnen heißt)->Neuer Menüeintrag Titel z.B. „Kontakt“, Menüeintragstyp „Breezing Forms“  Add Form. Dann unter dem Tab „Add Form“ den Namen des Formulars eintragen. Das sollte es gewesen sein, mit etwas Glück sieht das jetzt ungefähr so aus:

evi_kontaktformular

evi_kontaktformular

Anmerkung: wenn man das Formular in einen Beitrag anbinden will, braucht man zusätzlich das Breezing Forms Plugin, Info dazu gibts hier bei Crosstec.

Glitch oder Feature?

Ich hatte bei der Vergabe eines eigenen Formularnamens das Problem, dass die Anzeige nicht funktionierte „evisformular could not be found“. Wenn ich dann in der Formularverwaltung nachgeschaut habe, stand der Formularname wieder auf dem von Breezing Forms automatisch vergebenen Namen „QuickForm231612383“ drin, mit dem funktionierte es dann auch. Möglicherweise ein Glitch wegen der nicht ganz perfekten Installation auf dem neuen Xampp, vielleicht auch ein Feature  – sehr unbefriedigend, ich gebs zu, aber immerhin gibt es einen Workaround.

Fazit:

Wenn man sich mal an den etwas unhandlichen Formulareditor gewöhnt hat, läßt Breezing Forms keine Wünsche offen, es läßt auch die Erstellung komplexer mehrseitiger Formulare zu und bietet unzählige Konfigurationsoptionen. Eingehende Nachrichten werde auch automatisch mitprotokolliert, die kann man sich unter Komponenten->Breezing Forms-> Einträge verwalten anzeigen lassen, das gefällt mir dann doch sehr gut. Zugegeben, in Contact Form 7 ist das alles ein bisschen intuitiver, aber die Funktionsvielfalt von Breezing Forms ist schon beeindruckend.

Jedenfalls haben wir jetzt auch unser simples Kontaktformular mit recht wenig Aufwand realisiert, und dabei lassen wir es für heute.

Erweiterungen installieren: kleines Beispiel

Da fehlte doch noch was im Joomla-Inselfischkochbuch: das Zufallsrezept geht noch ab! Kurzes Googlen ergab, dass „Random Article“ von Artur Alves genau das können sollte, was ich brauchte. Also los:

Erweiterung installieren

Erweiterungen->Verwalten-> Installieren, hier sollte man sich bequemerweise den Tab „Aus Webkatalog installieren“ aktivieren, dann gehts genauso wie in WordPress mit dem Plugin-Verzeichnis. Erweiterung mit dem Namen suchen, wenn man die richtige gefunden hat wird man vom Assistenten durch die Installation geführt.

Modul anlegen

Mit Erweiterungen->Module->Neu->Random Article kann man sich jetzt ein eigenes Modul für den zufällig ausgewählten Artikel anlegen. Unter „Article Source Options“ wählt man sich die Kategorie aus, aus der der Zufallsartikel kommen soll, man könnte hier auch Subkategorien einbeziehen, aber die habe ich (noch) nicht. Namen für das Modul vergeben, darf ruhig „Zufallsrezept“ heissen, speichern.

Neuen Menüeintrag und Beitrag anlegen

Viele Wege führen in diesem Fall nach Rom, ich packe das neue Modul wieder in einen eigenen Beitrag und ordne diesem einem Menüeintrag zu.

Menüs->Main Menu->Neuer Menüeintrag-> Name „Zufallsrezept“, Menüeintragstyp einzelner Beitrag, den kann man hier gleich neu anlegen. Im Beitragseditor die Option Module anklicken und hier unser eben neu erstelltes Modul auswählen, beliebigen Text dazuschreiben, speichern und fertig. Wenn alles richtig geklappt hat, steht im Editor jetzt ungefähr sowas:

{loadmodule mod_random-article,Zufallsrezept}

Das kann man sich schon mal merken, diese Syntax wird uns noch öfter begegnen. Das wars jetzt aber auch schon, wir haben unser Zufallsrezept jetzt auch eingebaut.

Meckerpunkt am Rande: die Erweiterungs-Verwaltung

Wenn man unter Erweiterungen->Verwalten sowas wie den Pluginmanager erwartet, guckt man zuerst mal ganz schön, da springen einem neun Seiten mit mehr oder weniger kryptischen Einträgen entgegen. Weil hier nämlich auch die systeminternen Erweiterungen, Module und Komponenten mit angezeigt werden, und da fasst man tunlichst erstmal gar nichts an. Benutzerfreundlich ist das nicht, hier hätte ich mir eine übersichtlichere Lösung gewünscht!

 

 

 

Beitragskategorien aus der Datenbank abfassen

Für Spitzenklöppler: das WordPress-Kategorienmodell

Um an die Beitragskategorien heranzukommen, muss man sich mit sage und schreibe 5 Tabellen herumschlagen. Das kommt daher, weil die WordPress-Entwickler das Kategorienmodell unbedingt mehrstufig anlegen mussten. Das ist zwar wunderbar verschachtelbar und ergibt ganz eindrucksvolle Baumstrukturen, aber datenverarbeitungstechnisch ist es meiner Meinung nach mit Kanonen auf Spatzen geschossen. Mit einer winzigen Ausnahme (die Backrezepte im Inselfisch-Kochbuch) habe ich noch in keinem meiner Blogs eine Unterkategorien-Ebene gebraucht, und damit das hier nicht allzu unübersichtlich wird, lasse ich es auch bei der einen Ebene. Haben sie ein bißchen Zeit? dann wollen wir mal.

Die relevanten Tabellen

Erstens natürlich die wp_posts, aus der holen wir uns die ID, also den Primärschlüssel der Beiträge. Dann brauchen wir noch:

  • wp_term_relationships
  • wp_term_taxonomy
  • wp_terms
  • (wp_termmeta, nein, die brauchen wir nicht, nur der Vollständigkeit halber erwähnt)

Warum das ganze mit Term und nicht mit Category bezeichnet ist: rein theoretisch kann man sich auch noch eigene Taxonomien anlegen, die dann eben nicht Kategorie heissen sondern einen eigenen Namen kriegen. Sowas hab ich anno Dunnerkeil mal in meinem Bilderblog gemacht, da gabs eine eigene Taxonomie „Jahreszeiten“, die bestand aus genau vier Einträgen, nämlich „Frühling, Sommer, Herbst, Winter“. Bin ich wieder davon abgekommen, ich hab die Jahreszeiten einfach in die erste Kategorieebene mit aufgenommen, geht auch und ist wesentlich einfacher zu verwalten. Aber das nur am Rande bemerkt, wir holen uns die Tabellen jetzt mal ins Access rein und basteln uns die nötigen Verknüpfungen.

Das Datenmodell im Detail

Die ersten beiden Tabellen: wp_term_relationships und wp_posts

Wichtig ist hier erstens die object_id, das ist die ID des Beitrags aus der wp_posts. Einem Beitrag können ja mehrere Kategorien zugeordnet sein, deshalb tauchen die IDs hier auch mehrfach auf. Die term_taxonomy_id verweist auf die Kategorie. Die term_order könnte man für eine benutzerdefinierte Sortierung der Kategorien verwenden, aber das geht jetzt zu weit, das lassen wir weg.

screenshot_term_relationships

screenshot_term_relationships

Wir basteln uns also die erste Verknüpfung mit der object_id auf die wp_posts.

screenshot_beziehnungen_posts_relationships

screenshot_beziehnungen_posts_relationships

Die dritte Tabelle: wp_terms_taxonomy

Hier wird es schon ein bißchen undurchsichtiger. Die ersten drei Felder ID, term_taxonomy_id und term_id haben alle den selben Wert, da kann man nur raten wofür welches gut ist. Da wir nur die term_taxonomy_id aus der wp_term_relationships eindeutig zuordnen können, nehmen wir die halt, und merken uns als Hauptschlüssel die ID. Im Feld taxonomy steht immer der Wert category, wir haben ja nur diese eine Taxonomie, das können wir auch weglassen. Interessanter wäre da noch das Feld „parent“, das die übergeordnete Kategorie im Falle verschachtelter Kategorieebenen enthält, aber auch das lassen wir mal aussen vor, sonst blickt hier kein Schwein mehr durch.

Kleine Kuriosität am Rande: hier wird ein count mitgeführt, der die Anzahl der Beträge zu einer Kategorie wiederspiegelt. Kann man das nicht nachher im Rahmen einer Abfrage berechnen?

screenshot_term_taxonomies

screenshot_term_taxonomies

Unsere Beziehungen sollten jetzt so aussehen:

screenshot_beziehungen_3

screenshot_beziehungen_3

Die vierte Tabelle: wp_terms

Na gottseidank, da blickt man wenigstens halbwegs durch. Die term_id können wir aus der wp_term_taxonomy zuordnen, der name (na endlich!) ist der Name der Kategorie, slug ist auch klar, und die term_group ignorieren wir einfach.

screenshot_wp_terms

screenshot_wp_terms

Jetzt kommt endlich Butter bei die Fische, wir können unsere Beziehungen vervollständigen.

screenshot_beziehungen_4

screenshot_beziehungen_4

Haben wir da nicht noch was vergessen?

Die Tabelle wp_termmeta

Ja, die gibts auch noch, aber ehrlich gesagt weiß ich nicht so ganz genau, wofür man die verwenden könnte, die zieht nur wenn man mit mehreren Taxonomien arbeitet. Bei marketpress gibt es eine gelehrte Abhandlung dazu, ich hab sie allerdings nicht ganz verstanden, muss ich zugeben. Nachdem die Tabelle allerdings bei mir immer leer ist, ignoriere ich sie schlicht und ergreifend.

Sonst noch was? Ach ja, ich hätts beinah vergessen:

Die Tags = Schlagwörter stecken in der selben Logik

Und zwar wird für die Schlagwörter eine eigene Taxonomie „post_tag“ angelegt. Ich verwende prinzipiell keine Schlagwörter, wenn sie es getan haben lassen sie sich nicht irritieren, uns reichen die Beziehungen über die Kategorien.

Und jetzt: die Abfrage der Kategorien über alle vier Tabellen

Anmerkung: damit das hier nicht total uferlos wird, beschränke ich mich hier auf eine Kategorieebene. Sie sehen gleich, warum: Wir holen uns zunächst mal eine Auswahl relevanter Daten aus allen vier Tabellen, der SQL sieht dann so aus:

SELECT wp_posts.ID, wp_posts.post_title, wp_term_relationships.object_id, wp_term_relationships.term_taxonomy_id AS wp_term_relationships_term_taxonomy_id, wp_term_taxonomy.term_taxonomy_id AS wp_term_taxonomy_term_taxonomy_id, wp_term_taxonomy.term_id AS wp_term_taxonomy_term_id, wp_term_taxonomy.taxonomy, wp_term_taxonomy.count, wp_terms.term_id AS wp_terms_term_id, wp_terms.name
FROM wp_terms INNER JOIN ((wp_posts INNER JOIN wp_term_relationships ON wp_posts.[ID] = wp_term_relationships.[object_id]) INNER JOIN wp_term_taxonomy ON wp_term_relationships.[term_taxonomy_id] = wp_term_taxonomy.[term_taxonomy_id]) ON wp_terms.[term_id] = wp_term_taxonomy.[term_id];

Das Ergebnis: eine schon mal relativ übersichtliche Tabelle

Hier taucht jedes Rezept so oft auf, wie es Kategorien zugeordnet hat. Wenn wir jetzt ausser den Kategorien noch Schlagwörter mit drin hätten, müssten wir die herausfiltern, aber haben wir nicht, alles brav nur Kategorien.

screenshot_kategorien_rohdaten

screenshot_kategorien_rohdaten

Ein kleiner Kunstgriff: die Abfrage auf der Abfrage

Damit ich mir keinen Wolf parametrisiere, habe ich einfach auf die eben gezeigten Rohdaten (die Abfrage heisst auch kategorien_rohdaten) eine zweite Abfrage aufgesetzt, die ist schon übersichtlicher:

SELECT Count(kategorien_rohdaten.[ID]) AS AnzahlvonID, kategorien_rohdaten.[name]
FROM kategorien_rohdaten
GROUP BY kategorien_rohdaten.[name];

Auf Deutsch: ich zähle nur die Beitrags-IDs zu jeder genannten Kategorie, und fasse pro Kategorie die Summe zusammen. Das Ergebnis:

screenshot_kategorien_endergebnis

screenshot_kategorien_endergebnis

Na bitte, geht doch 🙂

Nur noch ein kleiner Glitch ist drin: die Summe beim Backwerk stimmt nicht. Das kommt daher, dass ich bei den Backwerken drei Unterkategorien angelegt habe, nämlich „Kuchen und Torten“, „Weihnachtsbäckerei“ und „Pikante Bäckereien“. Allerdings erlaubt es einem WordPress beim Erstellen oder Bearbeiten eines Beitrags, eine Unterkategorie anzugeben ohne auch die übergeordnete Hauptkategorie anzukreuzen, das habe ich offensichtlich einige Male gemacht, und daher stammt der Zählfehler. Die Korrektur ist einfach: ich entferne die Kategorie Backwerk und behandle die drei Unterkategorien wie Kategorien erster Ordnung, mein Excel für das Tortendiagramm kann mit Unterkategorien eh nix anfangen 🙂

Ich überlasse es jedem, der mit mehr als einer Kategorieebene gearbeitet hat selber, da die Logik entsprechend rauszupfriemeln, da muss man in der wp_terms_taxonomy den parent berücksichtigen, das ist mir jetzt hier zuviel Gedöns. Das hier langt jetzt nämlich echt für einen Beitrag, der hier ist lang genug – schließlich ist ja schon fast Feiertag!

 

 

 

 

 

 

 

 

Kategorien im Inselfisch-Kochbuch, statistisch aufbereitet (kleine Schummelei)

Der einfache Weg – ich schummle ein bißchen

Ich lass mir ja die Beitrags-Kategorien im Inselfisch-Kochbuch in der Sidebar anzeigen, mit der Anzahl der jeweiligen Beiträge, das sieht so aus:

screenshot_kategorien

screenshot_kategorien

Und weil ich manchmal ein bißchen ein Faulpelz bin, kopier ich mir den ganzen Schamott als unformatierten Text in eine Spalte ins Excel rein, hacke mir in der zweiten Spalte die Anzahlen manuell rein und bastel mir mein erstes Tortendiagramm:

Rezeptkategorien-Diagramm

kategorien_torte

kategorien_torte

Nanü, ich hab also am allermeisten vegetarische Rezepte eingestellt? Darüber liesse sich debattieren, schließlich habe ich auch alle Kuchen, Torten und Süßspeisen als „vegetarisch“ kategorisiert. Kann ich aber damit leben, darunter fallen nämlich auch alle Salate und Gemüsezubereitungen, und sowas esse ich täglich, das hat schon seine Richtigkeit.

Rang zwei mit 99 Rezepten hat die Kategorie „Für Kinder“, und auch das hat seine Richtigkeit, denn schließlich stelle ich auch viele Rezepte aus meiner Kinderzeit aus Omas Küche ein, die werden von den Kiddies heute auch noch geliebt!

Der Rest spiegelt getreulich wieder was ich selber oft und gerne esse. Mir sind gute Saucen genauso wichtig wie das Stückchen Fleisch auf dem Teller, und meine ganz große Liebe gehört der Mittelmeerküche. Ausserdem esse ich viel Gemüse, und Kuchen gebacken wird bei mir auch regelmäßig.

Fazit: Ins Inselfisch-Kochbuch kommen nur Rezepte, die garantiert ausgetestet sind und die bei mir selber oft auf den Tisch kommen. Deshalb sind auch die Zubereitungsbeschreibungen sehr genau und gut nachzuvollziehen, so daß die Rezepte leicht und gelingsicher nachzukochen sind. Mein Publikum mag es so – Rezepte für jeden Tag sind gefragt, keine ausgefallenen Exoten! Ich bleibe bei dieser Philosophie, und schreibe weiter nur das hinein, was ich auch selber gern koche und esse.

Ja, aber das war doch geschummelt!

Klar wars geschummelt – aber die Kategorien zu den Beiträgen aus der WordPress-Datenbank zu holen ist ein Späßchen für sich, und dazu gibt es einen neuen Beitrag.

 

 

Beitragsstatistik: weil mir das Dashboard da nicht reicht

Da waren die WordPress-Programmierer ein bißchen sparsam

Zugegeben, eine rudimentäre Beitragsstatistik läßt sich auch im Dashboard unter „alle Beiträge“ ablesen. Lesen, wohlgemerkt, wenn man da aussagekräftige Auswertungen fahren will, steht man ganz schön auf dem Schlauch, da kann man sich die Zahlen nur abschreiben, und das ist ein mühselig Spiel. Schon die allereinfachsten Statistiken wie z.B. Anzahl der Beiträge über die Tage gerechnet kann man sich zwar am Bildschirm angucken, aber wie zum Geier kriegt man die Daten da raus und rein ins Excel? Pfiffkas, da braucht man schon wieder Plugins dafür… ähem, Spaß muss sein, wir machen das natürlich anders 🙂

Ran an die Datenbank

Die meisten Daten von Interesse, wenn es um die Beiträge geht, stecken in der WordPress-Haupttabelle, der wp_posts. Die kennen wir ja schon recht gut, und die klemmen wir uns jetzt mal und schubsen sie aus MySQL raus und rein ins Access, da lässt es sich besser werken. Ich nehme wieder die Daten aus dem Inselfisch-Kochbuch, da war am meisten los.

Anmerkung am Rande: eine Access-2010-Lizenz gibts ab um die 30 €, wer öfter mal ein handliches Datenbankerl braucht sollte über diese Investition nachdenken!

Da hat sich ganz schön was angesammelt übers Jahr

Auf gehts, raus aus MySQL via CSV für Excel, Zeichensatz Windows 1250, Erste Zeile enthält Feldnamen anhaken und Schuß! Rein in Access, darauf gucken dass das Feld post_content den Datentyp Memo kriegt, und jetzt fangen wir richtig an.

1543 Datensätze bei 316 Rezepten – ganz schön viel Holz, aber das filtern wir uns gleich mal zurecht. Das ist jetzt alles Wiederholung, ich schalt mal den Schnellgang ein.

  • unser Erfassungszeitraum startet am 29.10.2016. Das Inselfisch-Kochbuch gibts zwar schon länger, aber da habe ich es nach einem katastrophigen Providerwechsel neu aufgebaut.
  • Ende-Datum ist gestern, 21.12.2017.
  • Uns interessieren eigentlich nur die veröffentlichten Rezepte, die erkennt man am post_type = post und post_status = publish.

Daraus stricken wir unsere erste Abfrage, wir nehmen erstmal nur wenige Felder mit, für den Anfang reichen uns das Erstellungsdatum (post_date) und der Titel (post_title). Im Access-Abfrageassistenten sieht das ganz bequem so aus:

Datum und Titel

Datum und Titel

Und hier kommt noch für alle Hardcorer das SQL:
SELECT wp_posts.post_date, wp_posts.post_title
FROM wp_posts
WHERE (((wp_posts.post_status)=“publish“) AND ((wp_posts.post_type)=“post“));

Das Ergebnis hat die erwarteten 316 Datensätze und sieht doch schon mal sehr hübsch aus:

liste_datum_titel

liste_datum_titel

Und wo ist der Rest geblieben?

Immerhin 1227 Datensätze sind bei unserer Abfrage auf der Strecke geblieben, wer oder was sind die? Access zu Hilf!

  • 1192 Datensätze sind vom post_status „inherit“, davon wiederum 1120 vom post_type „revision“. Das sind die Revisionen, die man sich im Beitragseditor zurückholen kann, wenn man mal einen Beitrag verschlimmbessert hat und eine frühere Version wieder herstellen möchte.
  • 16 mal post_type = page, das sind Seiten, keine Beiträge.
  • 72 mal post_type = attachment, das sind die hochgeladenen Bilder
  • und noch ein bißchen Kleinkram, ein paar drafts vom post_type = nav_menu_item und ein Contact-Form-Seven-Formular, das wars dann aber auch.

Wir bleiben jetzt mal bei unseren 316 veröffentlichten Beiträgen = Rezepten. Hier kommt die erste Statistik, die:

Anzahl der veröffentlichten Rezepte pro Tag über den ganzen Erfassungszeitraum

rezepte_pro_tag

rezepte_pro_tag

Was sagt uns dieses zackige Diagramm? Ich habe von Ende Oktober 2016 bis Ende Januar 2017 Rezepte eingehackt wie der Weltmeister, das war erstens die Wiederherstellung aus dem Datenbankbackup und zweitens die gleichzeitige Überarbeitung aller Rezepte im Hinblick auf Barrierefreiheit.  Von April bis Juli hab ich dann noch die Nachzügler aus dem Backup eingehackt, und ab August läuft dann der Normalbetrieb, mit ein bis zwei Rezepten an einem Tag. Dazu nehmen wir mal zum Vergleich die:

Besucherentwicklung über den gleichen Zeitraum

Man kann ganz deutlich sehen, dass die Anzahl der eingestellten Rezepte und die Anzahl der Besucher über den gleichen Zeitraum nahezu nix miteinender zu tun haben.

ifkb_besucher_pro_tag

ifkb_besucher_pro_tag

Ich mach hier mal einen kleinen Kunstgriff (wen es interessiert: mit dem GIMP) und mache eine

Kombination beider Diagramme

Jetzt stimmt natürlich die Y-Achsenbeschriftung nicht mehr, aber das kann ich verschmerzen. Die blaue Linie ist die Anzahl der von mir eingestellten Rezepte, die grüne Linie zeigt den Besucherverlauf.

besucher_gegen_rezepte

besucher_gegen_rezepte

Fazit: meinen Besuchern ist es nicht so wichtig, dass ständig neue Rezepte eingestellt werden. Die kommen, weil sie ein bestimmtes Rezept über Google gefunden haben, und dann kommen sie wieder und wieder zum Schmökern und zum Nachschlagen. Zur Erinnerung: ich habe 2819 Stammkunden (erkenntlich an den individuellen IP-Adressen), die so oft hereinschauen, dass sie den Löwenanteil meiner über 50.000 Hits auf dem Inselfisch-Kochbuch ausmachen.

Ich lerne daraus

Ja, was eigentlich? Dass ich mit dem Inselfisch-Kochbuch auf einem guten Weg bin, ein treues Stammpublikum habe und mir keinen Streß machen muss, weil ich nicht täglich neue Rezepte einstelle. Das läuft prima so wie es ist, die Besucherzahlen haben insgesamt eine leicht steigende Tendenz, das ist ein gesundes Wachstum und sehr erfreulich.

Und damit lass ich es für heute mal gut sein. Morgen gibts noch mehr WordPress-Zahlenschubserei,versprochen!

 

 

Noch mehr Zahlenschubserei: Besucher im schwarzen Pinguin

Ich machs kurz, ich verspreche es! 🙂

Die Besucherstatistik vom schwarzen Pinguin 2017

Vom Start der Zählung am 10.2.2017 bis gestern,  21.12.2017 waren es insgesamt 8704 Besucher an 316 Tagen im letzten Jahr, macht 27,5 Besucher pro Tag. Als Rohdiagramm sieht das so aus:

exceldiagramm besucher pro tag

besucher pro tag

Da ist im September ein Ausreisser dabei, das war 132 mal die selbe IP-Adresse, scheint ein Hack-Versuch gewesen zu sein. Den nehmen wir mal raus, der verzerrt mir die Stat doch sehr. Dasselbe nochmal ohne den Hacker:

ohne_hacker

ohne hacker

Na, das nenne ich doch einen vernünftigen Geschäftsverlauf. Ich hab das Jahr recht ruhig angefangen, dann einen sehr aktiven Sommer hingelegt und so ab September wieder ein bißchen weniger geschrieben. Da wärs jetzt natürlich interessant, wenn man die Besucherzahlen gegen die Anzahl meiner Beiträge gegenrechnen könnte, aber dazu kommen wir später. Jetzt gibts erst noch die Stammkunden, also alle, die öfter als einmal auf der Seite waren, das waren 970 Leutchen. Wie man hier sieht, waren die meisten so etwa zwischen 5 mal und 15 mal da:

stammkunden

stammkunden

Auch das ist eine sehr zufriedenstellende Gauss’sche Glocke, wie es sich gehört. Und damit laß ich es auch schon gut sein, jetzt gehen wir ans WordPress-Eingemachte, und dazu gibt es einen neuen Beitrag.

Alle alten Programmierer lieben Zahlenschubsereien – Besucherstatistik im Inselfisch-Kochbuch

„Trau keiner Statistik, die du nicht selbst gefälscht hast!“

Das ist mein Motto seit den ersten Stat-Vorlesungen an der Uni in den frühen 80er Jahren. Und es ist heissa! Jahresende und Zeit für einen statistischen Jahresrückblick.

Unser gutes altes WordPress sitzt ja auf einer wunderbaren Datenbank, und Datenbanken sind heissbegehrtes Statistikerfutter. Ich nehme mir mal mein Inselfisch-Kochbuch vor, das lebt und ist das ganze Jahr gepflegt worden, wollen mal sehen was wir da an statistischen Auswertungen rauskriegen. Es wird schon lange mal wieder Zeit für ein bißchen Spaß auf der Datenbank!

Was natürlich die SEO-Freaks interessiert: der Besucherzähler

Aber klar doch, den nehmen wir uns als Erstes vor. Ich verwende das leichtgewichtige Visitor Counter Plugin , das ist problemlos in der Installation und Anwendung. Es schreibt die statistischen Werte in eine eigene Tabelle weg, die heißt (Präfix-)vcp_log und ist damit einfach zu lokalisieren. Als CSV für MS Excel exportieren, und der Spaß kann losgehen…  aber halt! Ich schubs die ganze Sache natürlich in mein Leib- und Magen-Datenbankerl rein, das feine alte Microsoft Access, da kann ich Auswertungen fahren bis die Schwarte knackt 🙂

Visitor Counter Plugin: die Rohdaten

Schauen wir uns die Tabelle vcp_log mal kurz an, die ist übersichtlich genug. Es gibt drei Felder:

  1. LogID
  2. IP
  3. Time

und das wars schon. Die LogID ist ein Autoinkrement und interessiert nicht weiter, die IP-Adresse ist selbsterklärend und der Timestamp als Datum und Uhrzeit auch.

Aber ansonsten kanns jetzt mal losgehen: Time in Tagesdatum umwandeln, Gruppieren, Anzahl von IP ausgeben, Excel-Liniendiagramm draus machen und schon haben wir diese hübsche Grafik der Besucher pro Tag:

Excel-Diagramm Neue Besucher pro Tag

Excel-Diagramm Neue Besucher pro Tag

Kurze Analyse des Diagramms

Wow, was war Anfang September los? Der Peak mit den fast 700 Besuchern kommt von der Veröffentlichung des Inselfisch-Kochbuchs im Newsletter des Bayrischen Blinden- und Sehbehinderten-Verbandes, das ist ganz eindeutig zuzuordnen.

Ansonsten ist der Grafik noch zu entnehmen, dass die Anzahl der Besucher sich übers Jahr bei ungefähr 100 – 200 pro Tag eingependelt hat, Tendenz leicht steigend.

Was die Grafik nicht zeigt – nicht zeigen kann – ist die Anzahl der „Wiederholungstäter“. Ich weiss aber aus vielen persönlichen Kontakten, dass das Inselfisch-Kochbuch ein treues Stammpublikum hat, viele kommen immer wieder, auch mehrmals die Woche, und schauen ihre Lieblingsrezepte nach oder gucken obs was Neues gibt. Die gibts aber ein andermal, das sprengt mir hier sonst den Beitrag.

Was wir noch machen können: die Uhrzeit

Dabei kommt eine kleine Überraschung heraus: angeblich hatten wir Nachts um 1 die meisten  Besucher:

Excel-Diagramm Besucher nach Uhrzeit

Excel-Diagramm Besucher nach Uhrzeit

Das glaube ich ja noch nicht ganz! Wollen mal sehen, wenn der Timestamp in GMT (Greenwich Mean Time) angegeben sein sollte, sind wir mit der MEZ eine Stunde voraus, und mit der Sommerzeit sogar zwei Stunden. Dann läge der Peak so bei ca. 11 Uhr abends, das glaub ich ja schon eher, da guckt man nach der Sportschau nochmal in den Computer. Das würde auch den relativ niedrigen Stand zwischen 21 und 23 besser erklären, wenn das in echt 19 – 21 Uhr war, da sind die Leute beim Abendessen, das haut schon eher hin!

Und noch ein bisschen Kleinkram

Seit Beginn der Zählung am 29.10.2016 hatten wir 51789 Besucher insgesamt, nur in 2017 (bis gestern, 21.12.) waren es 45172. Das macht im Durchschnitt rund 123 Besucher pro Tag, in 2017 waren es pro Monat im Schnitt 3771. Spitzenreiter war der September mit 5367 Besuchern insgesamt, s. oben.

Nachgereicht: die „Wiederholungstäter“

Also, gucken wir da noch mal genauer hin: wir hatten insgesamt 51789 Besucher. Wenn ich mir die nach der IP-Adresse gruppiere, bleiben noch 8479 übrig. Das heisst, jeder Besucher ist im Schnitt 6,11 mal im Inselfisch-Kochbuch gewesen. Das geht natürlich noch genauer, ich klemm mir mal alle, die öfter als einmal da waren (das waren 2819 Stammkunden) und bastel mir ein Diagramm:

Besucher öfter als einmal

Besucher öfter als einmal

Na wer sagts denn, das sieht doch einer Gauss’schen Glocke verdammt ähnlich! Die allermeisten Besucher kommen anscheinend so zwischen 30 und 70 mal im Jahr, damit kann ich prima leben. Der Ausreisser am Anfang mit über 400 Hits war übrigens wahrscheinlich ein Hacker, der hat die Seite im Sekundenrythmus angesurft. Den muss man aus der Stat  rausnehmen, dann siehts so aus:

Ohne Hacker

Ohne Hacker

Na bitte, geht doch! Eine wunderbare Normalverteilung, wie aus dem Lehrbuch. Ich lieeebe Statistik! 🙂

Und das genügt jetzt auch mal fürs Erste! Natürlich wollen wir auch noch Stats über die Rezepte und Kategorien und so weiter fahren, aber dazu gibts einen neuen Beitrag.

 

Ein dicker, fetter WordPress-Bug: die Sache mit den Alt-Texten

Warum sind Alt-Texte so wichtig?

Wenn man Bilder in seine Webseite einfügt, kann man viel falsch machen. Zum Beispiel (was in WordPress leicht passiert) keinen Alt-Text einfügen, oder nur einen kryptischen Dateinamen wie DSC73635.JPG, so wie es aus der Digicam kommt, verwenden. Dabei ist der Alt-Text immens wichtig, wenn man barrierefreie Webseiten gestalten will, weil er für User von Screenreadern und anderen Hilfsmitteln die einzige Möglichkeit ist, Informationen über Bilder  zu erhalten. Und auch für nicht barierrefreie Seiten gilt: der Alt-Text ist nach W3C ein „required“ Attribut, also eine Pflichtangabe.

Bilder einfügen in WordPress: schnell mal drübergeklickt

WordPress bietet zwar beim Hochladen über die Mediathek die Möglichkeit, einen Alternativtext zum Bild einzugeben, aber es meckert auch nichts an wenn man dieses Feld leer läßt und ein Bild ohne Alt-Text hochlädt. Hier gehört eine Prüfung hin, die den Anwender auf den Fehler hinweist!

Wenn sie übrigens beim Bilder hochladen vergessen haben,  alt-Texte anzugeben, wird der jeweilige Dateiname dafür verwendet. Das ist gängige Praxis, aber nicht schön, weil der Screenreader dann eben -zig mal DSC01648 oder sowas vorliest, und das bringt natürlich überhaupt nichts.

Und sogar wenn man brav seinen Alt-Text eingibt, hat WordPress so seine Schwierigkeiten mit der Verwaltung. Das hatte ich in einem Beitrag über die Bildausgabe schon einmal erwähnt, aber es ist ein derart kapitaler Bug, daß ich ihn jetzt nochmal ausführlich beschreibe. Ich muß jetzt mal ein bißchen ausholen, um das näher zu erklären.

Wo landet der Alt-Text auf der Datenbank?

Zur Erinnerung: das Bild als solches landet in der wp_posts mit dem Post Type attachement. In der wp_postmeta  gibt es dann tatsächlich noch  einen Datensatz mit einem Fremdschlüssel, der die ID unseres Bild-Datensatzes aus der wp_posts enthält. Da wo im Feld meta_key das Schlüsselwort _wp_attachment_image_alt steht, da steckt daneben im Feld meta_value der alt-Text.

Das klingt soweit ja noch ganz gut, aber was, wenn man Alt-Texte nachträglich ändern will oder muß?

Dann passiert folgender blühende Unsinn:

Wenn sie jetzt im visuellen Editor hingehen und das jeweilige Bild bearbeiten, können sie zwar einen neuen, besseren alt-Text eingeben, aber der wird mitnichten in der Datenbank im Feld meta_value gespeichert! Der landet nur im img-src-Tag im post_content, und die Datenbank kriegt nichts mit davon. Wenn sie das Pferd jetzt andersherum aufzäumen und in der Mediathek das richtige Bild raussuchen, hier auf Bearbeiten gehen und da einen neuen alt-Text eingeben, landet der zwar in der Tabelle wp_postmeta (beim Metakey _wp_attachment_image_alt) aber nicht im Beitrag. Man müßte erst das betreffende Bild aus dem Beitrag löschen und aus der Mediathek wieder neu hereinnehmen, dann dürfte wieder das Datenbankfeld für den alt-Text herangezogen werden.

Übrigens: wenn sie den Alt-Text im visuellen Editor geändert haben und jetzt eine programmgesteuerte Ausgabe der alt-Texte via get_image_attribute() oder Ähnlichem probieren, kriegen sie natürlich die falschen Alt-Texte angezeigt, nämlich die aus der wp_postmeta, und nicht die aus dem img-src-Tag. Schöner Sch…, nicht wahr?

Konsequenzen dringend nötig

Das ist ein richtiger dicker, fetter Bug, da gibts kein Schönreden. Und es ist besonders ärgerlich, weil eben die Alternativtexte für die Barrierefreiheit so wichtig sind! Da dürfen sich die WordPress-Entwickler in Bälde etwas einfallen lassen, das Thema „Accessibility“, wie die Barrierefreiheit im Englischen heißt, ist auch in USA aktuell und taucht dort immer öfter in den Medien auf. Es gab auch schon spektakuläre Gerichtsurteile gegen Firmen, die ihre Webseiten nicht nach den Regeln der Barrierefreiheit gestaltet haben. Da darf man gespannt sein, wie der Gesetzgeber reagiert! Accessibility oder Zugänglichkeit von Webseiten ist eben ein brandaktuelles Thema, nicht nur bei uns.

 

Noch mehr postmeta: benutzerdefinierte Felder in wooCommerce

Falls ihnen die 48 vordefinierten Felder in wooCommerce noch nicht reichen, haben sie auch die Möglichkeit, zusätzliche Felder anzulegen. Diese laufen unter dem Stichwort „benutzerdefinierte Felder“ und können im Produkt-Editor angelegt werden.

Ein Feld für Material

Zu dem in meinem Online-Lädchen verkauften Glasperlenschmuck lege ich jetzt mal ein benutzerdefiniertes Feld „Material“ an.  Das kriegt dann zum Beispiel den Wert „Böhmische Glasperlen“, das sieht im Editor so aus:

benutzerdefinierte_felder

benutzerdefinierte_felder

Keine Hexerei, und was auf der Datenbank passiert kann man leicht erraten:

material_postmeta

material_postmeta

Es wird ein neuer Datensatz mit dem meta_key „Material“ angelegt, der kriegt den meta_value „Böhnmische Glasschliffperlen“. Das war’s schon, mehr ist nicht passiert.

Wie verwendet man nun diese Felder?

wooCommerce weist einen da höflich auf den Codex zum Thema Custom Fields hin. Das ist zwar gut gemeint, aber nicht besonders hilfreich. Deswegen gibts bei Tante Google auch jede Menge Einträge, wenn man nach „woocommerce show custom fields“ sucht, hier ist ein besonders netter von Theme Location

Der Knackpunkt ist: man muss die wooCommerce-Templates editieren, wenn man seine benutzerdefinierten Felder auch beim Produkt angezeigt kriegen will. Wir versuchen uns mal an einem einfachen Beispiel. Da sollen wir eine Zeile im Template content-single-product.php ergänzen:

<?php echo get_post_meta( get_the_ID(), ‘Material’, true ); ?>

Edit die content-single-product.php – ja, wie?

Also, erstmal muss man das richtige Template finden, und das ist bei der endlosen Latte von wooCommerce-Templates gar nicht so einfach. Schauen sie mal rein unter Plugins/wooCommerce/Bearbeiten, das ist alles andere als übersichtlich. Die content-single-product.php steht in der langen Liste ziemlich weit unten.

„At the appropriate place“ soll diese Zeile rein, heißt es im Tutorial, und das ist eine Runde Trial and Error. Ich habs jetzt im ersten Anlauf noch nicht hingekriegt, da muss ich nochmal ne Runde googlen. So richtig Spaß macht das nicht, die wooCommerce-templates sind viel zu schlecht dokumentiert, das ist eine einzige Raterei.

Anderer Ansatz: wooCommerce Hooks

Ich hatte jetzt relativ schnell die Schn… voll von der Rumprobiererei und bin auf einen anderen Lösungsansatz gestossen, um unser benutzerdefiniertes Feld auch anzeigen zu lassen. WooCommerce bietet eine lange Latte von vordefinierten Hooks, in die man sich einklinken kann, das ist hier bei BusinessBloomer recht ausführlich dokumentiert, man muss sich allerdings anmelden, um das Tutorial anschauen zu können, und dazu hatte ich keine Lust. Ein andermal vielleicht…

Prinzipiell sollte es so funktionieren: man editiert die functions.php und fügt den entsprechenden Hook hinzu, in dem ruft man die zugehörige selbstdefinierte Funktion auf, und die Funktion letztendlich sollte unser Custom Field dann auch anzeigen. Ich habs nicht hingekriegt, jedenfalls nicht in unter einer Stunde, und da hatte ich dann einfach keinen Bock mehr. Ist vielleicht nicht mein Tag zum Rumprobieren heute.

Noch ein Versuch: vielleicht mit einem Plugin?

Das hier sieht ganz gut aus:

WooCommerce Custom Product Data Fields

Das schau ich mir mal an, aber ich glaube, ich brauch erstmal ’ne Pause. Ja kruzitürken, kann das denn so schwer sein, so ein lumpiges Custom Field auch anzeigen zu lassen?

Ist echt nicht mein Tag heute, die Doku zu dem Plugin ist gerade nicht erreichbar.

acf_nicht_ereichbar

acf_nicht_ereichbar

Hab ich noch ein anderes Plugin probiert, ACF for WooCommerce.

ACF  = Advanced Custom Fields. Aber zu früh gefreut: auch kein Glück, da muß ich mal direkt die Support-Seite zitieren:

  • It seems only to work on Checkout Page. How do I show field on the Product Page?

    Any answer is most welcome, thank you.

Viewing 6 replies – 1 through 6 (of 6 total)

Tscha, Pech gehabt. Die Anzeige der Custom Fields in der Single Product Ansicht geht hier nur mit der kostenpflichtigen Pro-Version des Plugins, und die kostet 29 $. No way, José.

Jetzt reichts mit der Probiererei – noch einmal mit System.

Also, wir fangen nochmal sauber von vorne an. Wo soll unser benutzerdefiniertes Feld „Material“ erscheinen? In der Startseite des Shops, jedenfalls reicht mir das für’s erste. Direkt nach dem Titel, vor dem Warenkorb-Button.

Dafür editieren wir die woocommerce/templates/content-product.php.

Durch schlichtes Ausprobieren und Raten habe ich schließlich die richtige Position gefunden: nach der Zeile:

do_action( ‚woocommerce_shop_loop_item_title‘ );

Das hat nicht auf Anhieb funktioniert, da WordPress im Template anscheinend die get_post_meta()-Funktion nur mit ein bißchen Überredungskunst akzeptiert. Ich habe dann folgendes Snippet gefunden, damit kriegen wir endlich den meta_value unseres Custom Fields „Material“ angezeigt :

global $wp_query;
$postid = $wp_query->post->ID;
echo get_post_meta($postid, ‚Material‚, true);
wp_reset_query();

Ergebnis- meine benutzerdefinierten Felder werden jetzt direkt unter dem Titel jedes Produkts angezeigt:

shop_mit_cf

shop_mit_cf

Na bitte, geht doch. Aber ein Gfrett war das jetzt schon!

Wie gehts jetzt weiter?

Wenn man das benutzerdefinierte Feld noch woanders anzeigen möchte: tscha, das wird jetzt ein Exempel in Trial&Error. Für jede Seite im Shop herausfinden, welches Template für die Anzeige verwendet wird, dort die Stelle suchen an welcher das Custom Field erscheinen soll, da das obige Code Snippet einfügen und hoffen dass es funkioniert. Viel Spaß mit Tante Google und der wooCommerce-Doku…

Ich finde das Thema Custom Fields in wooCommerce insgesamt wahnsinnig unübersichtlich und lausig schlecht dokumentiert. Anscheinend gibt es einige Plugins, die einem da das Leben leichter machen sollen, aber ich hab bislang nur kostenpflichtige Exemplare gefunden, die das auch können was wir brauchen. Und ich zahle nicht für Plugins, Punktum. OpenSource, sie wissen schon. So, und das ist ein schöner Schlußsatz für diesen Beitrag, lassen wir es mal gut sein.

Die bessere Alternative zum -zigfachen Join: Kreuztabelle

Also, zuerst mal dieses: ich habe versucht herauszufinden, ob MySQL Kreuztabellen (Pivot Tables) kann oder nicht, und die Tendenz beim Googlen geht zu eher nicht. Jedenfalls gibt es keinen Transform-Befehl, man muß sich da irgendwie anders behelfen.

Ich habe da die tollsten Konstrukte gefunden, hier ein besonders Hübsches mit einem Case für jedes Feld… na, das ist ja wohl nicht der Weisheit letzter Schluß. Da greife ich doch lieber auf meine Leib- und Magendatenbank zurück, nämlich Microsoft Access. Ich bin ja sonst kein Microsoft-Fan, aber das gute alte Access ist einfach eine tolle Datenbank mit einem sagenhaften Bedienkomfort im Entwurfsmodus. Auch wenn die zugrundeliegende Jet-Engine schon viele Jahre auf dem Buckel hat, im intuitiven Zusammenstellen aller möglichen Arten von Abfragen ist Access echt ungeschlagen.

Was wollen wir erreichen?

Wir haben ja im letzten Artikel gesehen, daß wooCommerce zu jeder Bestellung mindestens 48 Einträge in der wp_postmeta anlegt. Ich hätte jetzt gerne einen tabellarischen Überblick über alle Bestellungen, mit allen 48 Werten aus der wp_postmeta zu jeder Bestellung.

Das heißt im Klartext: eine Tabelle mit den relevanten Daten aus der wp_posts, und allen 48 Meta Keys als Felder in einer Zeile. Auf jeden Fall brauchen wir einen Join von der wp_posts auf die wp_postmeta über die ID der Bestellung, und dann noch die Meta Keys als Feldnamen, befüllt mit den Meta Values. Klingt schaurig kompliziert, ist aber in Access relativ einfach machbar, nämlich mit einer Kreuztabelle.

Der SQL für die Kreuztabelle

…sieht so aus:

TRANSFORM First(postmeta_alle_orders.meta_value) AS ErsterWertvonmeta_value
SELECT postmeta_alle_orders.post_id, postmeta_alle_orders.post_title, postmeta_alle_orders.post_status, postmeta_alle_orders.post_type
FROM postmeta_alle_orders
GROUP BY postmeta_alle_orders.post_id, postmeta_alle_orders.post_title, postmeta_alle_orders.post_status, postmeta_alle_orders.post_type
PIVOT postmeta_alle_orders.meta_key;

Den kann man sich mit Hiilfe des Kreuztabellen-Assistenten erstellen und dann im Entwurfsmodus komfortabel editieren.

Das Ergebnis der Kreuztabelle

Ich habs mal schnell der Übersichtlichkeit halber in ein Formular gepackt (auch hierfür hat Access einen prima Assistenten), da sieht dann z.B. unser Datensatz mit der Nummer 42 so aus:

formular_kreuztabelle

formular_kreuztabelle

Na, da hat man wenigstens mal alle Felder im Blick. Wenn man jetzt noch wüßte, für was die alle gut sind… aber da lasse ich jeden selber raten, anhand der Feldnamen müßte man da relativ weit kommen.

Wie kann man es übersichtlicher machen?

Wir haben jetzt wenigstens ein bißchen den Überblick gewonnen, mit 7 Zeilen Jet-SQL statt 48 mal Join und Case. Die Krux ist halt, dass es von vorne herein ein Unding ist, einem Datensatz so viele Werte redundant zuzuordnen.

Wenn sie nur mal die vielen Felder anschauen, die etwas mit Adressen zu tun haben, die gehören ausgelagert! Da gehört ein Fremdschlüssel auf die Kundennummer rein, und zu den Kunden-Basisdaten in einer eigenen Tabelle legen wir uns noch eine schnuckelige zweite Tabelle mit Rechnungsadresse und Lieferadresse (falls abweichend) des Kunden an, das wars dann und ist sauber gelöst.,

Damit können die ganzen Adressfelder aus den Bestellungen rausfliegen, das macht so über den Daumen gepeilt schon mal etwas mehr als 20 Felder weniger. Genauso sieht es mit den Zahlungsmodalitäten und den Steuerinformationen aus, auch die gehören normalisiert und ausgelagert, das wären dann noch mal ein rundes Dutzend Felder weniger.

Aber… die wooCommerce-Entwickler wissen ja anscheinend nicht, wie man Daten normalisiert und Detailtabellen anlegt, deshalb dieser unüberschaubare Datenwust. Das ist einfach nur grottenschlecht programmiert, da beißt die Maus kein Faden ab. Es kann sich ja jeder selber überlegen, wie ein sauberes Datenmodell für die Bestellungen aussehen könnte, so als Fingerübung zum Entspannen 😉

Ich mach hier mal Schluß, und überleg mir ein neues Thema. See you demnächst, ich wünsche gute Erholung vom wooCommerce-Datenchaos!