MailChimp ändert Anmeldeformulare auf Single-Opt-in

Eine Freundin, deren WordPress Website ich erstellt habe und die MailChimp für ihren Newsletter verwendet, hat vor ein paar Stunden folgende E-Mail erhalten und mit weitergeleitet:

In dieser E-Mail kündigt MailChimp an, dass ab dem 31. Oktober alle Anmeldeformulare auf eine Single-Opt-in Verfahren umgestellt werden, statt dem bisherigen Double-Opt-in.

Ein riesiges Problem für Websites in Europa

Sie wusste nicht genau, was das für sie bedeutet, aber als ich die E-Mail gesehen habe, konnte ich kaum glauben, was ich da lesen musste. Das Double-Opt-in Verfahren ist das einzige zulässige, bei dem man berechtigt ist, die Empfänger auf der E-Mail-Liste anzuschreiben. Hierzu muss muss jeder Empfänger seine Eintragung in diese Liste “ein zweites Mal bestätigen”, indem er nach dem eigentlichen Anmeldeformular zusätzlich noch auf einen Link in der Willkommens-E-Mail klickt. Nur so wird sicher gestellt, dass der Empfänger sich selbst angemeldet hat und dem späteren Empfang von Newslettern zustimmt.

Viele Unternehmen in den USA oder anderen Teilen der Welt haben dieses Verfahren vermutlich nicht gemocht, führte es doch dazu, dass einige potentielle Empfänger diesen Link niemals geklickt haben und daher auch nicht angeschrieben werden durften. Aber genau dieses Double Opt-in Verfahren ist fundamental wichtig für Europa. Es stellt aktuell den einzigen legalen Weg dar, eine E-Mail-Empfängerliste anzulegen. Jeder Single-Opt-in Verfahren birgt die Gefahr einer Abmahnung oder anderer rechtlicher Konsequenzen. In Deutschland ist das mit dem “Gesetz gegen den unlauteren Wettbewerb” begründet.

Wie kann man das Problem beheben?

Am Ende der E-Mail befindet sich ein Link, der zu einer Einstellungsseite führt, auf der man alle Listen auswählen kann, für die man das Double-Opt-in Verfahren wieder aktivieren möchte:

Ich kann nur jedem Webseitenbetreiber in Deutschland (und wohl auch in allen anderen europäischen Ländern) nur dringend empfehlen, diese Einstellung unverzüglich vorzunehmen.

Update: Solltet ihr die Mail (noch) nicht bekommen haben, versucht mal folgenden Link: https://admin.mailchimp.com/lists/opt-in-status/

Fazit

Selbst wenn MailChimp gute Gründe für diesen Schritt haben sollte, so kann ich dennoch nicht verstehen, wie sie dies auch für bestehende Formulare umsetzen können und wieso sie ihre Kunden gerade einmal eine Woche vorher informieren. Es war schon immer schwierig, um nicht zu sagen gefährlich, MailChimp in Deutschland einzusetzen. Mit dieser Änderung werden sich wohl einige Kunden nach Alternativen wie etwa CleverReach umsehen.

Haftungsausschuss

Ich bin kein Anwalt, daher sind alle Informationen nach besten Wissen und Gewissen geschrieben worden. Kontaktiert also im besten Fall einen Fachanwalt, um eure persönliche Situation einschätzen zu lassen.

Customizer Optionen mit Polylang übersetzen

Wenn es um das Übersetzen von WordPress Seiten geht, ist mein Lieblingsplugin MultilingualPress. Für ein neues Kundenprojekt mit sehr kleinem Budget, das nur wenige statische Seiten hatte und bei dem eine Multisite nicht umbedingt notwendig war, haben wir uns aber für Polylang entschieden.

Probleme bei der Übersetzung der Inhalte

Einer der Hauptgründe, weshalb ich MultilingualPress gegenüber den anderen Lösungen bevorzuge ist die Tatsache, dass es auf die Multisite-Funktionalität von WordPress aufsetzt. In diesem Fall ist es nämlich sehr einfach wirklich jeden Bereich der Website zu übersetzen. Selbst die Verwendungen unterschiedlicher Themes, Plugins, Widgets, Menüeinträgen, usw. ist hiermit ohne weiteres möglich. Mit einer normalen WordPress Installation sind manche Texte nur einmal vorhanden, wie etwa die Einstellungen eines Plugins und die Customizer Optionen.

In dem erwähnten Projekt hat das Theme Customizer Optionen angeboten, um auf der Startseite im Header Kontaktinformationen direkt neben dem Logo zu platziern. Weiterhin konnte man den Text im Footer über eine Textarea überschreiben. Das braucht man auf einer deutschen Website auch meisten, da hier in der Regel die Links zu Impressum und Datenschutzerklärung positioniert sind. Diese Optionen mussten also übersetze werden, ebenso wie die Kontaktinformationen im Header, da hier Uhrzeiten angegeben waren.

Erstellung eines Child Themes für die Übersetzungen

Leider konnte ich keine Lösung finden, die mit der Codebasis des Themes umgesetzt werden konnte. Also habe ich mich dazu entschlossen ein Child Theme zu erstellen, das das Header- und Footer-Template überschreibt. Der Header sah in etwa wie folgt aus:

<div class="intro-wrap">
  <?php echo wp_kses_post( wpautop( get_theme_mod( 'header_intro' ) ) ); ?>
</div><!-- end .intro-wrap -->

Die Customizer Option header_intro wurde hierbei einfach nur ausgeben. Es gibt hier keinen Filter auf den Wert, den man verwenden konnte. Wie kann man den Text also dennoch übersetzen? Hierzu bietet die Polylang API die Funktion pll__, mit der der Wert vor der Ausgabe übersetzt werden kann:

<div class="intro-wrap">
  <?php echo wp_kses_post( wpautop( pll__( get_theme_mod( 'header_intro' ) ) ) ); ?>
</div><!-- end .intro-wrap -->

Nun kann der Text übersetzt werden, wenn eine solche Übersetzung für die aktuelle Sprache exisiert. Aber wie genau funktioniert die eigentliche Übersetzung der Option?

Texte für die Übersetzung registrieren

Damit man einen Text überhaupt erst übersetzen kann, muss man Polylang mitteilen, dass es ihn gibt. Hierzu wird die Funktion pll_register_string der Polylang API verwendet. In die function.php Datei fügt man einfach folgene Zeilen ein:

if ( function_exists( 'pll_register_string' ) ) :
	/**
	 * Register some string from the customizer to be translated with Polylang
	 */
	function child_theme_name_pll_register_string() {
		pll_register_string( 'header_intro', get_theme_mod( 'header_intro' ), 'child-theme-name', true );
	}

	add_action( 'after_setup_theme', 'child_theme_name_pll_register_string' );
endif;

Zuerst wird überprüft, ob die Funktion existiert, da es ansonsten zu einem Fatal Error kommen würde, sobald Polylang deaktiviert wird. Anschließend wird eine Callback-Funktion registiert, in der die Funktion zur Registrierung von Texten verwendet wird. Der erste Parameter ist hierbei lediglich ein Name zur Sortieung der übersetzbaren Strings. Der zweite Parameter ist der eigentliche Text, der übersetzt werden soll. In diesem Fall ist es der dynamische Wert der Customizer Option. Der dritte Parameter definiert eine Gruppe für der String und der letzte besagt, dass es sich bei der Text um einen mehrzeiligen Text handelt. Somit wird bei der Übersetzung im Backend eine Textarea und kein einzeiliges Textfeld verwendet.

Den Text übersetzen

Alle reigistrierten Strings befinden sich unter “Sprachen -> Übersetzungen von Zeichenketten” im Backend. Hier steht in einer Tabelle in der ersten Spalte der aktuelle Wert aus dem Customizer und in der letzten Spalte kann dieser Text dann pro Sprache übersetzt werden. Hierbei ist zu beachten, dass bei jeder Änderung des Wertes in der Customizer Option auch die Übersetztung neu vorgenommen werden muss, da ansonten der unübersetzte Wert in allen Sprachen verwendet wird.

Fazit

Es ust auch mit Polylang möglich, die verschiedenen Optionen des Customizers pro Sprache anzupassen. Hierzu muss aber in den meisten Fällen ein Child Theme erstellt werden. Die Übersetzung von Optionen eines Plugins können schon viel schwieriger werden, da man hier nicht einfach ein “Child Plugin” erstellen kann. Dabei ist man dann meistens auf Filter angewiesen, die das Plugin dann hoffentlich anbietet, um Texte anzupassen. Das ist auch ein weiterer Grund, wieso ich bei mehrsprachigen Seiten eher zu einer Multisitelösung tendiere.

Bonustipp

Da Polylang ein noch eher neues Plugin ist, sehr viel neues als WPML (das ich in der Regel nicht nutze), unterstützt es das sogenannten WPML language configuration file wpml-config.xml, was einem ein bisschen Arbeit erspart. Wenn also das Theme sagt, dass es “WPML ready” ist und eine solche Datei mitliefert, können eventuell einige der Schritte übersprungen werden, die ich in diesem Beitrag gezeigt habe,

Global WordPress Translation Day 3

Am Samstag den 30. September fand der dritte Global WordPress Translation Day rund um den Globus statt. Ab Mitternacht UTC gab es ein 24h Programm mit insgesamt 22 Päsentationen.

Lokale Events

Wie schon bei den ersten WP Translation Days gab es viele lokale Events. Beim zweiten waren es noch 38, dieses mal mit 71 fast doppelt so viele (vielleich sogar mehr, die nicht offiziell angekündigt waren), davon sechs in Deutschland:

Weiterlesen →

Schlagwörter von privaten Beiträgen in der Tag-Cloud anzeigen

Keine Angst, an den letzten Wochenenden gab es mal kein WordCamp und daher gibt es heute mal wieder einen normalen Beitrag 😉 Vorletzte Woche gab es an einem Kundenprojekt eine interessante Anfrage. Die WordPress Website hatte einen FAQ-Bereich und manche Fragen waren auf privat gesetzt. Die Website hat außerdeme eine Tag-Cloud eingesetzt, um es den Besuchern zu erleichtern, passende Fragen zu finden. Aber selbst, wenn sich die Nutzer angemeldet haben, konnten sie keine Schlagwörter in der Tag-Cloud sehen, die lediglich in privaten Fragen verwendet wurden.

Wie werden die Schlagwörter in der Tag-Cloud erzeugt?

Wenn in WordPress der HTML-Code für die Schlagwörter-Wolke erzeugt wird, dann werden nur eine begrenzte Anzahl an Schlagwörtern ausgelesen. Aber wie genau wird diese Auswahl berechnet? Man würde vermuten, dass hierzu eine Datenbank-Abfrage gestartet wird, die nach der Häufigkeit des verwendeten Schlagwortes gruppiert und die IDs zurückliefert, die am meisten verwendet wurden. Aber so funktioniert es nicht in WordPress. Aus Geschwindigkeitsgründen wird die Anzahl der Nutzung eines Schlagwortes statisch in einer Spalte in der Datenbanktabelle gespeichert. Aber wieso sind dann private Beiträge in der Tag-Cloud nicht sichtbar? Das liegt daran, dass sobald man die Sichtbarkeit eines Beitrags auf privat stellt, dieser Beitrag nicht mehr mitgezählt wird, wenn es um die Ermittlung der Gesamtanzahl geht. Nur öffentliche Beiträge werden hierbei beachtet. Es gibt also leider keinen einfachen Lösungsweg über einen Filter oder eine Action, um auch private Beiträge anzuzeigen. Aber wie können wir das Problem lösen?

Die Datenbankabfrage anpassen

Fadst jede Datenbankabfrage, die “eine Liste” erzeugt wird in WordPress durch die Klasse WP_Query umgesetzt. Für die Tag-Cloud ist es genau genommen die Klasse WP_Term_Query, die aber sehr ähnlich funktioniert. Wir müssen also lediglich die Abfrage ändern, die hierbei ausgeführt wird. Aber wie stellen wir fest, dass es sich bei der aktuellen Abfrage um die Tag-Cloud handelt und nicht im eine andere Abfrage auf Taxonomien? Es gibt leider keinen Conditional-Tag is_tag_cloud() oder ähnliches.

Im Grunde ist es recht einfach. Bei der Erstellung der Schlagwörter-Wolke werden zwei Argumente eingesetzt, die nur hier vorkommen: largest und smallest. Diese beiden Werte geben an, welches die größte bzw. kleinste Schriftgröße ist, die in der Tag-Cloud verwendet werden soll. Wir können also einfach prüfen, ob einer dieser beiden Argumente vorhanden ist und wissen dann, dass es sich bei der aktuellen WP_Term_Query um die Abfrage für die Tag-Cloud handelt. Der Rest ist eigentlich recht einfach. Wir müssen nur den term_clause Filter verwenden, um die SQL-Abfrage entsprechend anzupassen:

function private_posts_in_tc_terms_clauses( $pieces, $taxonomies, $args ) {
	if ( isset( $args['largest'] ) && is_user_logged_in() ) {
		// Count by the grouped term_id.
		$pieces['fields'] .= ', COUNT(t.term_id) AS grouped_count';
		// Join the relationship to the posts.
		$pieces['join'] .= ' INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id';
		// Remove the "redundant" count (only for public posts).
		$pieces['where'] = str_replace( 'AND tt.count > 0', '', $pieces['where'] );
		// Group by the term_id to remove duplicates and calculate the count.
		$pieces['where'] .= ' GROUP BY tt.term_id HAVING grouped_count &gt; 0';
	}
	
	return $pieces;
}
add_filter( 'terms_clauses', 'private_posts_in_tc_terms_clauses', 10, 3 );

Bevor wir die Abfrage anpassen, müssen wir natürlich noch sicherstellen, dass der aktuelle Nutzer auch angemeldet ist und die privaten Schlagwörter auch sehen darf. In der veränderten Abfrage machen wir dann einen JOIN auf die term_relationship Tabelle und gruppieren anhand der Term-ID. Hierdurch können wir dann mit SQL sehr einfach die Anzahl inklusive der privaten Beiträge berechnen. Die Abfrage selbst ist natürlich etwas langsamer als die Originalabfrage, da sie keine zwischengespeicherten Werte aus der Tabelle verwendet. Aber da ohnehin jede WP_Term_Query in einem Transient zwischengespeichert wird, ist die Performance-Einbuße nicht wirklicht groß.

Fazit

Es ist nicht immer ganz so einfach, dass man nur den richtigen Hook finden muss, um eine Query in WordPress zu ändern. Aber normalerweise gibt es fast immer einen Weg, das gewünschte Ergebnis zu erreichen. Wenn ihr diese Funktion auch mal ausprobieren wollt, dann findet ihr den Code dazu wie immer in einem GIST. Hier könnt ihr euch auch wieder alles als ZIP-Datei runterladen und einfach als Plugin auf eurer Seite installieren.

WordCamp Zagreb – Eine Reise zur kroatischen Community

Ein weiteres Wochenende, ein weiteres WordCamp, eine neue Stadt … gut, eigentlich sogar ein neues Land in Europa, das ich besucht habe. Nur zwei Wochen nach meiner Reise zum WordCamp in Brighton bin ich vorletztes Wochenende nach Zagreb gereist, der Hauptstadt von Kroatien, um eine neue europäische Community kennenzulernen.

Donnerstag: Ankunft in Zagreb und Warm-up

Mein erste Flug ging von Berlin nach Wien, die Stadt, in der letztes Jahr das WordCamp Europe stattgefunden hatte. Von dort aus ging es dann wenig später gleich weiter nach Zagreb. Da es in Zagreb sehr heiß war, war ich sehr dankbar, dass mich Lucijan und Emanuel vom Flughafen abgeholt und in die Stadt gefahren haben. Dort ging es zuerst einmal in meine sehr spezielle Unterkunft 🙂

Am Abend hatte das Organisationsteam ein paar Plätze in einem netten Restaurant im Stadtzentrum reserviert. Hier konnte ich schon die ersten Teilnehmer kennenlerenen und ein nettes kleines inoffizielles Warm-up genießen.

Freitag: Workshop-Tag

Auf immer mehr WordCamps findet man in letzter Zeit Workshops. Da ich mich im Vorfeld zu keinem Workshop angemeldet hatte, bin ich am Freitag dann einfach zu zwei englischsprachigen gegangen, die angeboten wurden. Die meisten anderen waren in kroatischer Sprache. Nur ein weitere war noch in Englisch: ein Workshop für Kinder. Eine wirklich tolle Idee!

The Art of Public Speaking

Der erste Workshop wurde von Luca Sartoni gehalten, einem Teilnehmer der italienischen WordPress community, der durch seine tollen Vortäge auf WordCamps bekannt ist. In einem Workshop hat er viele nützliche Tipps gegeben, wie man bessere Vorträge vorbereitet und hält. Er hat sich dabei nicht nur auf die Folien konzentiert, sondern auch mit dem Votrag selbst, also auch der Recherche, der Vorbereitung und allen notwendigen Schritten bis zum Event. Nach diesem Workshop hatte ich auch gleich ein paar Dinge gefunden, die ich an meinem Vortrag für Samstag verbessern konnte 🙂

The Irresistible Power of Strategic Storytelling

Mein zweiter Workshop war einer, in dem man mich als Entwickler nicht unbedingt erwarten würde. Aber da ich auch ein regelmäßiger Blogger bin, war das Thema “Storytelling” dann doch nicht ganz uninteressant für mich 😉 Nevena Tomović hat wirklich einen tollen Workshop gehalten. Nach einer kleinen Einführung wurden wir in Gruppen eingeteilt, und sollten an einer zufälligen Geschichte arbeiten, in der wir Leute davon überzeugen sollten, einen bestimmten Ort zu besuchen. Ich war der einzige in der Gruppe, der nicht aus Kroatien kam. Die anderen hatten die Idee, über einen Berg in der Nähe von Zagreb zu erzählen. Ich war sehr überrascht von mir selbst, wie viel Kreativität ich beim erzählen der Geschichte hatte, dann mehr als nur ein paar Stichpunkte konnten wir in der Zeit nicht zusammentragen. Eine wirklich tolle Erfahrung 🙂

Speakers-Dinner

Am Ende des Workshop-Tages gab es dan noch ein kleines Speakers-Dinner. Auch den zweiten Tag in Folge habe ich leckere kroatische Spazialitäten genießen können und viele interessante Gespäche mit Organizern, Speakern, Sponsoren und Volunteers führen.

Samstag: Konferzenz-Tag

Nach dem Workshop-Tag gibg es dann mit dem “Hauptteil” des WordCamps weiter, der im Museum für Zeitgenössische Kunst stattfand. Das WordCamp hatte zwei Tracks.

The Human-Centered Brand

Im ersten Slot gab es nur eine Session. Die Keynote wurde von Nela Dunato gehalten, die im letzten Jahr als beste Speakerin des WordCamp in Kroatien gewählt wurde. Sie hat einen sehr inspirierenden Vortag zum Thema Branding im persönlichen Kontext gegeben.

Plugin-Entwicklung

Ich habe fast den ganzen rechlichen Tag in Track B verbracht, der lauter Entwickler-Themen bereit hielt. Die ersten drei haben sich mit der Plugin-Entwicklung beschäftigt. Zuerst hat Ante Šepić über sein Setup zur Plugin-Entwicklung gesprochen. Es hat mich ein wenig überrascht, dass er explizit nicht die WordPress Coding Standards einsetzt, sondern die PSR-Standards, die auch viele PHP-Frameworks einsetzen. Der zweite Talk war von Ratko Šolaja, der ebenfall einen starken Fokus auf Code-Qualität gelegt hat und über seine “In’s and out’s” der Plugin-Entwicklung gesprochen hat. Der dritte Talk in der Reihe war von Goran Jakovljević, der sich mit der Entwicklung und dem Verkauf von Premium-Plugins beschäftigt hat. Foran hat ein einige gute Tipps zum Thema Preismodelle, sowie zum Service und Support gegeben. Ich habe noch immer nicht vor, ein Premium-Plugin zu veröffentlichen. Aber sollte ich es mal tun, habe ich jetzt einige gute Einblicke bekommen, wie man am besten anfängt.

DeSign everything

Direkt im Anschluss an die Plugin-Sessions hat Anastasios Manoloudis einen inspirierenden Vortrag zum Thema “Design” gegeben. Es hat sich dabei aber nicht auf das visuelle Design konzentriert, sondern auf andere Dinge, wie etwa die Sprache, die wir verwenden.

Why bother with code checking?

Eine Sache, die mir wirklich sehr an diesem WordCamp gefallen hat, war die Tatsache, dass alle Talks zum Thema Entwicklung die WordPress Coding Standards erwähnt haben. Denis Žoljom war hier keine Ausnahme und hat sein Augenmerk auf das Thema Code-Checking gelegt. Er hat verschiedene Tools vorgestellt, mit deinem man nicht nur den eigenen PHP-Code prüfen kann, sondern auch das CSS und JavaScript.

Vue.js with WordPress

Ich bin nicht wirklich ein JavaScript-Framework-Entwickler, daher war der Vortrag von Marko Banušić zu Vue.js sehr interessant für mich. Er hat dabei ein paar einfache Beispiele gezeigt, wie man bestimmte dynamische Bereichte der Website durch Vue.js Templates ersetzen kann.

WordCamps and why are they important

Als regelmäßiger WordCamp Teilnehmer musste ich dann Track B für die Session von Milan Ivanović verlassen. Er hat darüber berichtet, wieso WordCamp so wichtig sind. ich konnte mich wirklich mit vielen Geschichten identifizieren, die Milan erzählt hat.

Developing a new default WordCamp theme

Endlich konnte auch ich, auf meinem siebten WordCamp, das ich dieses Jahr schon besucht habe, meinen ersten Vortrag halten. Der Lead-Organizer Lucijan Blagonić, der mit mir zusammen im Design-Team des WordCamp Europe gewesen war, hatte mich gebeten, zum neuen WordCamp Theme einen Vortrag vorzubereiten, was ich natürlich gerne getan habe 🙂

Open Sources Of Inspiration

Im letzten Slot gab es wieder nur einen Vortrag in Track A. Den Abschluss hat Dario Jazbec Hrvatin gemacht, der nicht nur einen sehr inspirierenden Titel hatte 😉

Afterparty

Habe ich eigentlich schon das tolle kroatische Essen erwähnt? 😉 Auf der kleinen Afterparty direkt im Veranstaltungsort gab es nocht mehr davon. An den drei Tagen habe ich versucht, wirklich alles mal zu kosten und ich habe es wirklich fast alles gemocht.

Sonntag: Contribtor-Day

Das WordCamp Zagreb hatte seinen Contributor-Day am Sonntag. Etwa 30 Teilnehmer waren vor Ort und haben sich in vier Gruppen zusammengefunden: Core, Localization, Support and Community. Das Community-Team hat sich zu verschiedenen Themen der kroatischen COmmunity, aber auch zu denen Communites von Serbien und anderen Ländern in der Region unterhalten. Ich habe einigen neuen Core-Contributorn dabei geholfen, ihre ersetn Gehversuche zu machen, denn der Core-Team-Lead konnte leider nicht teilnehmen.

Walkingtour

Mein erstes WordCamp in Kroatien endete mit einer zweistündigen Stadtführung durch das Zentrum von Zagreb, in dem ich einiges über die Stadt und das Land erfahren konnte.

Fazit

Ich habe meinen ersten Ausflug nach Kroatien und mein erstes WordCamp Zagreb wirklich sehr genossen. Nichr nur das tolle Essen, auch die hervorragenden Vorträge und die gastfreundliche Community haben mit viel Freude bereitet. Auch die Tatsache, dass alle Session in Englisch waren, hat mir sehr dabei geholfen, möglichst viel mitnehmen zu können. So etwas hätte man von einem lokalen WordCamp nicht unbedingt erwartet. Ich würde wirklich gerne mal wieder zu einem WordCamp in Kroatien gehen. Nächstes Mal vielleicht in einer anderen Stadt 🙂