
Ratgeber
Die besten 14 Kabel. Nummer 9 wird dich erstaunen // Update: 11.12.2018 08:00
von Dominik Bärlocher
Gestern ist ein Listicle online gegangen, das bewusst dumm war. Warum? Es zeigt auf, dass Journalismus nicht zwingend von Menschen gemacht wird und dennoch effektiv sein kann. Denn ich habe das Listicle halbautomatisch generiert.
Du hast Listicles auch schon als dumm bezeichnet? Willkommen im Club. Du hast gestern mein Kabel-Listicle als dumm bezeichnet? Gut so, dann hast du erkannt, worum es geht. Denn Listicles sind dumm. Und ich zeige dir, wie dumm sie wirklich sind. Ich kann sie mittlerweile per Web App generieren. Halbautomatisch und fixfertig durchformatiert. Zeitersparnis nach einigen Stunden Development: Etwa eine Stunde pro Listicle.
Ich zeige dir, wie ich die Web App gebaut habe, was sie macht und wo ich sie noch weiter verbessern könnte.
Aber aus Sicht eines Webportals, das gerne Visitors hat, sind Listicles sehr interessant. Denn sie haben ein paar Hebel, die immer ziehen.
Damit spreche ich im Text deine Neugierde wie auch deine Emotionen an. «Ich bin mir sicher, dass Nummer 9 total unbeeindruckend ist», denkst du dir vielleicht und klickst drauf. Du willst wissen, was Nummer 9 ist und ob die Nummer 9 tatsächlich so scheisse ist, wie du erwartest. Portale wie Buzzfeed haben sich durch Titel wie «Die besten 14 Kabel. Nummer 9 wird dich erstaunen» ein Millionenpublikum aufgebaut. Wie loyal diese Millionen sind, ist eigentlich egal. Sie sind auf der Seite, haben die Bildli angeschaut und sich gedacht «So ein Käse», haben aber die Werbung angeschaut und Impressions und somit Geld generiert.
Aus journalistischer Sicht sind Listicles noch dümmer als aus Lesersicht. Denn, was viele vergessen: Irgendwer muss den Kehricht auch noch schreiben. Die Chefetage bei digitec findet das Konzept Listicle mal mehr, mal weniger interessant und im Rahmen des SEO-optimierten Wortes «Kaufratgeber» stehen auch Listicles zur Diskussion. Da diese aber immer nach demselben Schema funktionieren habe ich das automatisiert. Ich mag zwar keine Lust auf stundenlanges manuelles Formatieren haben, aber auf viel längeres stundenlanges Programmieren schon.
Damit ein Projekt wie mein sogenannter «Black Magic Listicle Generator» entstehen kann, müssen wir die Komponenten eines Listicles abstrahieren.
Wichtig ist die Erkenntnis, dass Listicles nicht gelesen werden wie ein Buch. Niemand interessiert sich für die Texte jenseits der Rangnummern und einer catchy Überschrift. Daher kann dieser Text vernachlässigt werden. Er muss aber da sein, damit Googles SEO-Algorithmen die Seite nach wie vor mögen und hoch rangieren.
Ein Listicle besteht aus folgenden Elementen, jetzt spezifisch auf digitec bezogen:
Der Begriff SEO ist jetzt schon öfter gefallen. Hinter ihm versteckt sich mehr Religion als Wissenschaft, denn damit macht Google gutes Geld. Es geht darum, dass die Indizierung Googles dich besser mag. Welche Kriterien reinspielen, ist nicht genau bekannt, aber einige gängige Praktiken haben sich etabliert. So darf eine Überschrift 3 nicht einer Überschrift 2 übergeordnet sein. Versionen einzelner Wörter – Smartphones, Phones, Natel, Telefon, Mobiltelefon – sollen den Suchradius verbreitern, selbst wenn Google mittlerweile selbständig abstrahiert. Und so weiter. Es gibt in jedem Medienunternehmen Kräfte, die sich von SEO umgehend eine Million oder mehr unique organic visitors versprechen und daher muss alles sofort SEO-optimiert sein, egal wie schlecht der Text sich nachher liest.
Von mir aus.
Ein Listicle ist also etwas, das Maschinen gefällt, von Menschen aber nicht gelesen wird. Warum sollte das dann auch nicht eine Maschine schreiben?
Ich programmiere dann und wann wieder gerne Web Apps, die einen recht spezifischen Dienst erledigen. Die haben eine Funktion, kein Error Handling und funktionieren in einem eng definierten Rahmen. Gut, ich bin der weltschlechteste Coder, aber einen dummen Listicle Generator kriege ich hin. Du auch.
Du brauchst:
Das Projekt, das wir anpacken, sieht zwar hübsch aus, kann aber mit «Quick and Dirty» recht gut beschrieben werden. Denn hinter den Kulissen wird alles etwas hacky wirken. Soll es auch, denn für Listicles lehnen wir uns nicht aus dem Fenster. Im Gegenteil, wir wollen so wenig wie möglich selbst machen.
Leg dir irgendwo auf einem Computer eine Ordnerstruktur an, die so aussieht:
root/
├── css/
│ └── styles.css
├── img/
│ ├── logo.png
│ └── favicon.png
└── index.html
Kurze Erklärung:
Für dieses Projekt brauchen wir eigentlich nur die JavaScript Library JQuery, aber ich habe mir mal vor vielen Monden ein Grundgerüst für Web Apps zusammengestellt, die so ziemlich jeden Use Case und jede Programmiersprache abdeckt, die ich für Web Apps brauchen kann. Der sieht so aus:
Experten sehen jetzt schon, wo der Teil, der hacky ist, reinkommt. Ich lade viel zu viel Zeug rein, das ich für ein kleines JQuery-Projekt nicht brauche. Aber ich habe nie behauptet ein besonders guter Coder zu sein. Zudem will ich die Zeit für ein Listicle nicht verschwenden. Ich geh lieber Bier trinken oder sowas.
Am Ende will ich einen Text, der folgendes Schema hat:
Damit wir eine möglichst vielseitige Webform abfüllen können, nicht viel eingeben müssen und möglichst schnell zum Resultat kommen, können wir die oben erwähnten Elemente eines Listicles noch weiter runterbrechen.
Ein Titel hat immer ein ähnliches, wenn nicht sogar dasselbe Format: «Die besten $zahl $productTypePlural. Nummer $zahl2 wird dich erstaunen»
Sowohl $zahl wie $zahl2 können wir vorerst ignorieren. Sie erfordern keinen menschlichen Input, denn hier ist noch ein Geheimnis der Listicles: Die besondere Nummer 9 ist komplett irrelevant. Bis jetzt weiss ich nicht, was Nummer 9 im gestrigen Listicle eigentlich ist. Ich habe mir die Gesamtanzahl vom Computer errechnen lassen und aus dieser Zahl dann eine zufällige als besonders kennzeichnen lassen.
$productTypePlural aber ist etwas schwieriger. Denn die deutsche Sprache ist grammatikalisch heikel. Ich muss der Maschine sowohl einen Singular wie auch einen Plural des Produkttypen übergeben. Im Titel brauche ich den Plural, im Zwischentitel dann den Singular.
Daher sieht das HTML für den Titel so aus:
Für den Zwischentitel muss ich der Maschine etwas Grammatik beibringen. Denn dieser liest sich in der aktuellen Version immer «Dieses Kabel». Ist natürlich automatisch generiert. Die Variablen hier heissen $productTypeThis und $productType.
Diese zwei Elemente behalte ich als freien Text. Das ergibt SEO-technisch am meisten Sinn. Und zwei, drei Sätze habe ich schnell geschrieben.
Der Zwischentitel «Dieses Kabel» setzt sich wie folgt zusammen:
var articleZwiti = productTypeThis + " " + productType
Dazu kommt nachher noch ein automatisch generierter Rang und etwas Formatierung.
Produkte betten wir in unserem Backend nach wie vor manuell ein. Dazu brauchen wir die Produktnummer, die praktischerweise in jeder URL zu einem Produkt verpackt ist.
Da wir aber eine beliebige Anzahl Produkte einbetten können, muss ich später mit einem Array arbeiten. Daher mache ich eine Text Area, die pro Zeile einen Link aus dem digitec Shop akzeptiert und damit arbeitet.
Da den Fülltext eh keiner liest, kann ich im Fülltext SEO-kompatible Wörter einspielen. Auch hier, Text Area mit einem Satz pro Zeile. Die erste Zeile wird später dem ersten Produkt zugeordnet, die zweite dem zweiten und so weiter.
Dazu habe ich unten einen Button integriert, denn mit diesen Angaben kann mein Generator arbeiten und ein komplettes Listicle erstellen.
Das Listicle wird in einer Textbox namens #listicleOutput ausgegeben
Bis jetzt macht die Webseite zwar einen hübschen Eindruck, hat aber noch keine Funktion. Da die Funktion nicht wirklich so besonders komplex ist, können wir hier mit JQuery arbeiten. Die JavaScript Library ist recht stark und versatil und daher perfekt für so Dinge, wie unseren lieblos hingesudelten Listicle Generator.
Im Script-Teil der Seite index.html können wir mit wenigen Zeilen Code recht viel bewirken. Zuerst aber müssen wir die ganzen oben festgelegten Begriffe in JQuery übernehmen. Das machen wir mit Variablen:
var productNumbers = $('#productNumbers').val()
var uselessSentences = $('#uselessSentences').val()
var productType = $('#productType').val()
var productTypePlural = $('#productTypePlural').val()
var productTypeThis = $('#productTypeThis').val()
var articleLead = $('#articleLead').val()
var articleIntro = $('#articleIntro').val()
Hier kommen zum ersten Mal auch digitec-spezifische Aspekte hinein. Wir arbeiten im Backend mit Markdown. Das heisst, wir können mit einfachen Zeichen vor einer Zeile Formatierungen schaffen, die dann von der Website übernommen werden. Das ist praktisch und im Alltag müssen die Marketing Manager und die Redaktoren nicht hundertmal mühsam Formatierungen zusammenklicken.
var zwitiPrefix = "## ";
var productPrefix = "[[product: ";
var productSuffix = "]]";
var doubleBreak = "\r\r";
Zur Erklärung: Wenn ich einen Zwischentitel mache, dann sieht der im Backend so aus:
## Zwischentitel
Ein eingebettetes Produkt so:
[product: 8287505]
Zwischen einzelnen Formatierungen müssen immer zwei Zeilenumbrüche sein, die ich mit var doubleBreak als Variable definiere. Mit diesen Formatierungen plus den Angaben aus obiger Form kann ich also mein Listicle zusammensetzen.
Ich bin aber faul. Ich will nur Links in meine Form reinpacken, denn so finde ich die Produkte für mein liebloses Listicle auch. Da noch manuell konzentriert Produktnummern herauszueditieren ist zu viel verlangt. Machen wir das automatisch.
var urls = productNumbers.split(/\s+/)
console.log(urls)
var mv = $.map(urls, function (val, i) {
if (val != "") {
var ju = val.split('?')[0]
pat = /[-|/](\d{5,8})$/
rv = pat.exec(ju)
if (rv !== null) {
console.log("Found id: " + rv[1])
return rv[1]
} else {
console.log(" Not matching html ")
}
}
})
Hier baue ich ein Array aus den URLs. In der Regel ist die Produktnummer ganz hinten an der URL.
https://www.digitec.ch/de/s1/product/caterpillar-s61-520-64gb-dual-sim-16mp-schwarz-silber-mobiltelefon-8287505
Wenn ich aber über die Filter der Website zu meiner Auswahl gelangt bin, dann macht die Seite ein Suffix, das die Filterung reflektiert, hinten an die URL.
https://www.digitec.ch/de/s1/product/caterpillar-s61-520-64gb-dual-sim-16mp-schwarz-silber-mobiltelefon-8287505?tagIds=82
Darum der .split mit dem Fragezeichen. Alles, was nach dem Fragezeichen kommt, wird verworfen. Danach suche ich eine Zahlenfolge von 5 bis 8 Ziffern und packe sie in ein Array. StackOverflow sei Dank habe ich sogar etwas wie Error Handling eingebaut.
Das zweite Array ist dann auch schnell gemacht, denn Texte sind etwas einfacher.
var lines = $('#uselessSentences').val().split(/\n/);
var texts = [];
for (var i = 0; i < lines.length; i++) {
// only push this line if it contains a non whitespace character.
if (/\S/.test(lines[i])) {
texts.push($.trim(lines[i]));
}
}
Habe ich von StackOverflow. Im Wesentlichen mache ich hier nichts anderes, als all die SEO-Sätze in ein zweites Array zu packen.
Damit haben wir alles, damit wir einen Aritkel bauen können. Das geht in JQuery easy mit .each:
$.each(mv, function (index, value) {
var articleZwiti = productTypeThis + " " + productType
$('#listicleOutput').append(zwitiPrefix + (index + 1) + ": " + articleZwiti + doubleBreak + productPrefix + value + productSuffix + doubleBreak + texts[index] + doubleBreak);
})
Ich nehme die Variablen oben, definiere kurz wie ein Zwischentitel aufgebaut ist, dann geht's los:
each macht das für jeden Eintrag in der Linkliste und sortiert den Satz aus dem zweiten Array dazu.
Beim Klick auf den Black Magic Button passiert das alles vollautomatisch und in #listicleOutput wird das fertig gebaute Listicle ausgespuckt.
Ein Listicle aber hat einen Titel. Den können wir automatisieren. Wir brauchen nur die Anzahl Einträge im Array (+1), dann eine zufällige Zahl aus der Anzahl der Einträge im Array.
var randomIndex = Math.floor(Math.random() * texts.length)+1;
var articleTitle = "Die besten " + texts.length + " " + productTypePlural + ". Nummer " + randomIndex + " wird dich erstaunen";
Die Variable randomIndex pickt zufällig eine Zahl aus dem Array raus und macht dann «Nummer 9 wird dich erstaunen». Mit dem Attribut .length sage ich JQuery, dass nicht der Inhalt, sondern die Länge des Arrays relevant ist.
Dieses Konstrukt schieben wir an den Anfang des Listicles:
$('#listicleOutput').prepend(articleTitle + doubleBreak + articleLead + doubleBreak + articleIntro + doubleBreak)
Voilà, das Listicle steht und kann 1:1 in unser Backend kopiert werden. Ein Listicle kann so lieblos in wenigen Sekunden hingesudelt werden.
Dieses Modell kann übrigens beliebig erweitert werden. Die Wälle aus Produkten auf digitec und Galaxus? Kein Problem. Irgendwelche Styling-Listen, wo ein gesamtes Outfit irgendwie dargestellt werden muss? Keine Sache. Menschlicher Fehler ist minimiert und inhaltlich sind wir zwar SEO-optimiert, aber nicht relevant.
Damit sind wir noch nicht ganz am Ende. Denn da wir so wenig Arbeit wie möglich am Listicle selbst machen können, können wir mit dem Knopfdruck einiges automatisieren.
Wenn wir das Listicle nicht automatisch kopieren, dann müssen wir im Feld #listicleOutput alles markieren, rechts klicken und dann kopieren, oder CTRL/⌘+C drücken. Wieder Risiko für menschlichen Fehler. Daher:
$("#listicleOutput").select();
document.execCommand('copy');
Das kopiert den ganzen Inhalt in die Zwischenablage. Können wir uns das also sparen. Ferner können wir uns die manuelle Suche nach einem passenden Bild oben sparen. Denn wir haben den Suchbegriff, den wir bei Google eingeben würden, bereits oben in $productType übergeben.
var searchURL = "https://www.google.ch/search?q=" + productType + "&tbs=sur:fc,isz:l,imgo:1&tbm=isch"
window.open(searchURL, '_blank')
Voilà, eine Google Image Search öffnet sich per Knopfdruck. Der Suffix hinten an der URL macht nichts anderes als folgende Filterungen in Google Image Search standardmässig bereits zu machen:
Denn kein Listicle ist komplett ohne belangloses Stock Photo oben.
Ich habe einen Narren an diesem Projekt gefressen. Denn mit wenig Effort kann der Generator viel mehr. Ich habe mir überlegt, ob ich ihm Aspekte wie «beste», «schönste» oder so übergeben kann, damit auch die nutzlosen aber SEO-optimierten Sätze entweder generiert werden oder aus einem Array ausgelesen.
So. Fertig. Ich mach mal wieder was, das etwas Recherche und Liebe erfordert. Journalismus, zum Beispiel.
Auf Wunsch aus der Kommentarspalte, hier ein GitHub-Repo mit dem Projekt. Lass mich wissen, wenn du was Cooles damit machst.
Journalist. Autor. Hacker. Ich bin Geschichtenerzähler und suche Grenzen, Geheimnisse und Tabus. Ich dokumentiere die Welt, schwarz auf weiss. Nicht, weil ich kann, sondern weil ich nicht anders kann.