Websupporter

Vor allem über WordPress.

Ein Script direkt nach dem HTML-Tag body einfügen

Immer wieder einmal müssen Scripte direkt nach dem öffnenden <body>-Tag eingefügt werden. Für Plugins war dies bisher eine schwierige Übung, denn an dieser Stelle gab es keine Funktion und keinen Hook über den man hätte gehen können. Möchte man beispielsweise den Google Tag Manager einfügen, so heißt es auf der Beschreibung, wie man das Script einfügen soll:

Copy the following snippet and paste it immediately after the opening <body> tag on every page of your website, replacing GTM-XXXX with your container ID

Wie man bisher vorgehen konnte

Doch in dieser Umgebung gab es bisher nur ein verlässliches Element in Themes: body_class(). Diese Funktion wird allerdings eingesetzt um die Klassen des body Tags zu bestimmen:

<html>
    <head>
    <?php wp_head(); ?>
    ...
    </head>
    <body <?php body_class(); ?>>
    ...
    </body>
</html>

Bisher mussten sich Plugins deshalb mit Hacks und Umwegen begnügen, direkt hinter dem öffnenden body-Tag ein Script zu hinterlegen. Üblicherweise hinterlegten Sie selbst einen Action-Hook und forderten die User auf, diesen Hook direkt hinter dem Tag zu platzieren, in etwa so:

<html>
    <head>
    <?php wp_head(); ?>
    ...
    </head>
    <body <?php body_classes(); ?>>
    <?php do_action('plugin_specific_action'); ?>
    ...
    </body>
</html>

Der Nachteil dieser Methode ist natürlich, dass die Administratorin manuell in den Child-Theme eingreifen muss, um diesen Hook zu hinterlegen.Ein anderer Weg war deshalb, die body_class() zweckzuentfremden:

<?php
add_filter('body_class', function( array $classes ) : array {
   $script = 'irgendein script';
   $classes[] = '">' . $script . '<br style="display:none';
}, 999);

Statt also einer weiteren Klasse hinzuzufügen konnte man so versuchen, den body-Tag zu schließen und das Script auszugeben. Doch das ist natürlich auch keine zufriedenstellende Lösung.

Auf dem Weg zu einer Lösung

Das Problem ist altbekannnt und schon seit neun Jahren gab es deshalb ein entsprechendes Ticket, WordPress entsprechend zu erweitern:

Ticket im Trac: „New action on body open“

Während des WordCamps US propagierte Matt Mullenweg, man wolle jetzt einmal Frühlingsputz betreiben, was den riesigen Ticketberg anging, der sich in den letzten Jahren angesammelt hatte. Eine Folge davon: Mit WordPress 5.2 wird dieses Ticket nun endlich geschlossen. Und: es wir einen neuen Templatetag geben, welchen Themes hinterlegen sollen: wp_body_open()

Was Themes nun tun müssen

Zukünftig sollen Themes hinter dem öffnenden body Tag nun diese Funktion ausführen. Alles was diese Funktion dabei macht: Sie führt den Action Hook wp_body_open aus. Plugins können sich also in diesen Hook einhängen, und können so Code direkt an dieser Stelle ausführen.

In der Ankündigung dieses neuen Template Tags heißt es ausdrücklich:

Bear in mind that using this hook should be reserved for output of unseen elements like <script> tags or additional metadata. It should not be used to add arbitrary HTML content to a page that could (and probably would) break layouts or lead to unexpected situations.

Der Hook soll also ausdrücklich nur dazu genutzt werden, Scripte und andere unsichtbare Elemente einzubringen.

Wenn Themes diese Funktion nun allerdings einbringen, bedeutet dies automatisch, dass sie nur noch auf WordPress 5.2+ funktionieren. Mach eine mag deshalb vor der Verwendung der Funktion zurückschrecken, wenn sie sich anguckt, welche Versionen derzeit von WordPress noch im Umlauf sind.

Aktuell genutzte WordPress Versionen (Stand: April 2019)

Noch immer laufen mehr als die Hälfte aller WordPress Installationen mit einer Version kleiner 5.0. Möchte man also sein Theme nach wie vor auch für ältere Versionen lauffähig halten wird folgender Code für die functions.php vorgeschlagen:

if ( ! function_exists( 'wp_body_open' ) ) {
  function wp_body_open() {
    do_action( 'wp_body_open' );
  }
}

Dies würde sicherstellen, dass die Funktion auf jeden Fall vorhanden ist. Wie man dies implementieren kann sieht man auch an diesem Commit für das _s Theme.

Was Plugins beachten sollten

Dennoch dürfte es vermutlich etwas dauern, bis man sich in seinem Plugin darauf verlassen kann, dass dieser Templatetag tatsächlich im Theme vorhanden ist. Pluginautoren könnten sich also überlegen, ob man dem Administrator eine kleine Information zukommen lässt, sollte das Theme die Funktion noch nicht nutzen. Ganz banal könnte dies vielleicht so aussehen:

add_action( 'wp_footer', function() {
  if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
    return;
  }
  if ( did_action( 'wp_body_open' ) ) {
    return;
  }

  echo '<div class="alert">Das Plugin XY funktioniert nur mit einem Theme, welches wp_body_open() unterstützt. Das aktuell verwendete Theme hält diesen Templatetag nicht bereit.</div>';
} );

Man könnte im Debug-Modus einfach eine Meldung ausgeben, wenn die entsprechende Aktion nicht ausgeführt wurde. Schöner wäre es natürlich, die Information statt in den Fuß der Seite dann im Adminbereich anzuzeigen oder ähnliches. Doch ich hoffe, dies gibt eine grobe Idee, wie man als Plugin darauf reagieren könnte.

Über den Autoren

Seine erste Webseite hat David Remer 1998 in HTML verfasst. Wenig später war er fasziniert von DHTML und JavaScript. Heute konzentriert sich vor allem auf das Entwickeln von WordPress Themes und Plugins für Inpsyde. Außerdem hat er das Buch "WordPress für Entwickler" verfasst.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.