Nützliche Code Snippets
In unserer WordPress-Agentur widmen wir uns intensiv der Programmierung und Anpassung von Websites. Da wir regelmässig auf wiederkehrende Codeabschnitte zurückgreifen müssen, haben wir eine praktische Übersicht erstellt, um unsere Hacks an einem zentralen Ort zu speichern.
Aufgrund des Interesses vieler unserer Kollegen, die ebenfalls Zugriff darauf haben wollten, entstand die Idee, diese Sammlung zu veröffentlichen und hoffentlich vielen weiterzuhelfen.
WordPress Hacks
WooCommerce Hacks
Enfold Hacks
Browser Tab Titel-Änderung (bei keinem Fokus)
Bilder in Mails einbetten per HTML
Bilder werden normalerweise in Mails als externe Links eingebettet. Dies hat einige Vorteile, dass dies zum Beispiel auf vielen Endgeräten angezeigt werden können. Der Nachteil ist, dass diese Bilder zuerst geladen werden müssen, wozu eine Warnung z.B. im Outlook bestätigt werden muss.
Bilder kann man auch einbetten. Dies hat auch Nachtteile:
- Mail wird viel grösser und übertragung dauert länger
- Bilder werden nicht in jedem Mailclient angezeigt
Um Bilder einzubetten, wird das Bild am besten auf die benötigte Grösse zugeschnitten, da die Dateigrösse entscheident ist, ob das Mail am Ende übertragen werden kann.
Anschliessend Uploaded man das Bild bei: https://www.base64-image.de/ und drückt auf „copy image“.
Im Newsletter kann nun ein Text / HTML Element eingefügt werden. Bei dem Text Element muss auf HTML gewechselt werden.
Danach fügt man foldenden Code ein:
<img src="" />
Innerhalb des src=““ fügt man nun den Inhalt ein, damit es danach etwa so aussieht:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE..." />
Danach ist das Bild Inline eingebunden und kann verschickt werden.
Vertical Scrollbare Table (responsive)
<div class="tableresponsiv"> <table width="100%">...</table> </div>
Und nehmen folgenden CSS Code im Stylesheet auf:
.tableresponsiv { width: 100%; padding: 0px; margin-bottom: 0px; overflow-y: hidden; border: 1px solid #DDD; overflow-x: auto; min-height: 0.01%; }
Email Links mit Betreff und Body
<a href="mailto:web@demo.ch?subject=Betreff%20mit%20Leerzeichen&body=Nachricht"> ... </a>
**Aufbau:**
subject= Hier steht der Betreff der Nachricht.
body= Hier steht die Nachricht.
Leerzeichen sollten immer gegen %20 ersetzt werden, was einem Leerzeichen entspricht. Sonst kann es zu Fehlern kommen.
Bindestriche und Umbrüche
Wort Umbrüche wenn zuwenig Platz vorhanden ist:
- macht Umbruch ohne Bindestrich:
<wbr>
- macht Umbruch mit Bindestrich, in Titel einsetzbar:
­
Kalendereinladung mit WordPress verschicken
Ab und an muss man unverständliche Dinge neu lernen. Der Versuch direkte Kalendereinladungen per WordPress zu versenden, endet im Disaster. Aber warum?
mail() ist eine PHP Funktion die Mails verschickt. wp_mail() ist die WordPress Funktion. wp_mail kann es aber nicht, da es den Code nicht korrekt formatiert und daher die Mails entweder mit einer ICS Datei ankommen, oder der Mailserver diese nicht lesen kann. Mit mail() umzusetzen ist möglich, aber ist aufwändig und nutzt nicht die WordPress Möglichkeiten.
Daher habe ich ein Zwitter gemacht. Ich nutze eine eigene Funktion, greife aber auf das Mailversandgerüst von WordPress zurück.
<?php function sendOutlookInvitation($participants, $subject, $desc, $start_time, $end_time, $location='') { global $phpmailer; if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) { require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php'; require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php'; require_once ABSPATH . WPINC . '/PHPMailer/Exception.php'; $phpmailer = new PHPMailer\PHPMailer\PHPMailer( true ); $phpmailer::$validator = static function ( $email ) { return (bool) is_email( $email ); }; } $phpmailer->addAddress($participants[0]); foreach ($participants as $i => $attendee) { if ($i >= 1) $phpmailer->addCC($attendee); } $phpmailer->WordWrap = 50; $phpmailer->isHTML(true); $urlparts = parse_url(site_url()); $organizer = $urlparts['host']; $text = "BEGIN:VCALENDAR\r\n". "VERSION:2.0\r\n". "PRODID:-//wukch-calender//mailer/NONSGML v1.0//EN\r\n". "METHOD:REQUEST\r\n". "BEGIN:VEVENT\r\n". "UID:" . md5(uniqid(mt_rand(), true)) . "wuk.ch\r\n". "DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z\r\n". "DTSTART:" . date('Ymd\THis', $start_time) . "Z\r\n". "DTEND:" . date('Ymd\THis', $end_time) . "Z\r\n". "SUMMARY:".$subject."\r\n". "ORGANIZER;CN=".$participants[0].":mailto:website@".$participants[0]."\r\n". "LOCATION:".$location."\r\n". "DESCRIPTION:".$desc."\r\n"; foreach ($participants as $i => $attendee) { $text .= "ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN".$attendee.";X-NUM-GUESTS=0:MAILTO:".$attendee."\r\n"; } $text .= "END:VEVENT\r\n". "END:VCALENDAR\r\n"; $headers = "From: ".$participants[0]."\n"; $headers = "Reply-To: ".$participants[0]."\n"; $headers .= 'Content-Type:text/calendar; Content-Disposition: inline; charset=utf-8;\r\n'; $headers .= "Content-Type: text/plain;charset=\"utf-8\"\r\n"; $phpmailer->Subject = $subject; $phpmailer->Body = $desc; $phpmailer->AltBody = $text; $phpmailer->Ical = $text; if(!$phpmailer->send()) { return false; } return true; }
Ich habe die Funktion gebaut, dass mir Kunden eine Einladung zusenden können an freien Terminen. Sich selbst muss man natürlich auch einladen. Die erste Mailadresse die angegeben wird, wird automatisch als Organisator verwendet:
<?php $participants = array('test@test.ch','kunde@domain.de'); $subject = 'Betreff der Mail'; $desc = "Beschreibung der Mail"; $start_time = gmttime(); // GMT Zeit des Start $end_time = gmttime() // GMT Zeit Ende $location = 'Zoom oder vor Ort' sendOutlookInvitation($participants, $subject, $desc, $start_time, $end_time, $location='');
Viel Spass damit.
Lazy Load Bilder von WordPress
Mit dem folgenden Code, werden alle Bilder auf Lazy Load bei WordPress umgestellt.
add_filter( 'wp_get_attachment_image_attributes', 'alter_att_attributes_wpse_102079', 20); function alter_att_attributes_wpse_102079($attr) { if (strpos($attr['class'], 'skip-lazy') === false) { $attr['data-original'] = $attr['src']; unset($attr['src']); if (isset($attr['srcset'])) { $attr['data-original-set'] = $attr['srcset']; unset($attr['srcset']); } $attr['class'] .= ' lazy'; } return $attr; }
Hooks debuggen
function debug_hook2() { echo "<p>--- Hook ---</p>";} function debug_hook($hook) { global $wp_filter, $debughook; $debughook = $hook; $arr = array(); foreach ($wp_filter[$hook]->callbacks as $nr => $ho) { $arr[$nr] = key($ho); } add_action($hook, 'debug_hook2',1); foreach ($arr as $nr => $ho) { add_action($hook, 'debug_hook2',$nr+1); } $out = "<pre>".print_r($arr,true)."</pre>"; return $out; } echo debug_hook('woocommerce_email_order_details');
Absender E-Mailadresse anpassen
add_filter( 'wp_mail_from', function() { return 'example@example.com'; } ); add_filter( 'wp_mail_from_name', function() { return 'Example'; } );
Local Google Fonts (Elementor)
Schriften werden anschliessend nicht mehr von gfonts geladen.
add_filter( 'elementor/frontend/print_google_fonts', '__return_false' ); add_action('wp_enqueue_scripts', 'google_fonts_local'); function google_fonts_local() { wp_register_style('google_fonts_local', plugins_url('fonts/stylesheet.css',__FILE__ )); wp_enqueue_style('google_fonts_local'); }
Schriften müssen danach weiterhin lokal über das CSS geladen werden und muss manuell eingebaut werden!
Site Health Checks deaktivieren
add_filter( 'site_status_tests', 'sitehealthcheck' ); function sitehealthcheck( $tests ) { unset($test); return $tests; }
Revisionen nach 2 Wochen löschen
if (!wp_next_scheduled('rev_cleanup')) { wp_schedule_event( time(), 'daily', 'rev_cleanup' ); } add_action( 'rev_cleanup', 'do_rev_cleanup', 10); function do_rev_cleanup() { global $wpdb; $abfrage = "DELETE a,b,c FROM wp_posts a LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id) LEFT JOIN wp_postmeta c ON (a.ID = c.post_id) WHERE a.post_type = 'revision' AND a.post_date < '".date("Y-m-d",strtotime('-2 weeks'))."';"; $wpdb->get_results($abfrage); }
Bestätigung für Änderung der Admin Mail deaktivieren
add_filter('admin_email_check_interval', '__return_false'); remove_action( 'add_option_new_admin_email', 'update_option_new_admin_email' ); remove_action( 'update_option_new_admin_email', 'update_option_new_admin_email' ); function wuk_update_option_new_admin_email( $old_value, $value ) { update_option( 'admin_email', $value ); } add_action( 'add_option_new_admin_email', 'wuk_update_option_new_admin_email', 10, 2 ); add_action( 'update_option_new_admin_email', 'wuk_update_option_new_admin_email', 10, 2 );
Fehler Mails von WordPress deaktivieren
Code muss in wp-config.php eingefügt werden:
define('WP_DISABLE_FATAL_ERROR_HANDLER', true);
Javascript mit weiteren Parametern einfügen (z.B. async)
add_action( 'wp_enqueue_scripts', 'add_theme_scripts',80); function add_theme_scripts() { wp_register_script('demo-js','https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'); wp_enqueue_script('demo-js'); } add_filter( 'script_loader_tag', 'add_demo_to_script', 90, 3 ); function add_demo_to_script( $tag, $handle, $source ) { if ( 'demo-js' === $handle ) { $tag = '<script data-ad-client="ca-pub-9175988955138834" async src="' . $source . '"></script>'; } return $tag; }
SVG Upload erlauben
add_filter('upload_mimes', 'cc_mime_types'); function cc_mime_types($mimes) { $mimes['svg'] = 'image/svg+xml'; return $mimes; }
Versionsnummern überall entfernen (Sicherheit)
if ( !is_admin() ) { // Sicherheitsstuff um Versionsnummern von WordPress zu verstecken add_filter( 'comment_class' , 'remove_comment_author_class' ); add_action( 'init', 'strip_wp_version', 1 ); add_filter( 'script_loader_src', 'strip_jscss_versions'); add_filter( 'style_loader_src', 'strip_jscss_versions'); } function strip_wp_version() { global $wp_version; $v = intval( rand(0, 9999) ); $d = intval( rand(9999, 99999) ); $m = intval( rand(99999, 999999) ); $t = intval( rand(999999, 9999999) ); if ( function_exists('the_generator') ) { remove_filter( 'wp_head', 'wp_generator' ,9999); $actions = array( 'rss2_head', 'commentsrss2_head', 'rss_head', 'rdf_header', 'atom_head', 'comments_atom_head', 'opml_head', 'app_head' ); foreach ( $actions as $action ) { remove_action( $action, 'the_generator' ); } $wp_version = $v; $wp_db_version = $d; $manifest_version = $m; $tinymce_version = $t; } else { add_filter( "bloginfo_rss('version')", create_function('$a', "return $v;") ); $wp_version = $v; $wp_db_version = $d; $manifest_version = $m; $tinymce_version = $t; } } function strip_jscss_versions($src) { if (stripos($src, "?ver=") OR stripos($src, "?v=")) { $src = explode('?v', $src); return $src[0]; } elseif (stripos($src, "&ver=") OR stripos($src, "&v=")) { $src = explode('&v', $src); return $src[0]; } return $src; }
Youtube DSGVO konform einbinden
add_filter( 'embed_oembed_html', 'WUK_iframe_proportion_wrap', 10, 4 ); function WUK_iframe_proportion_wrap ( $html, $url, $attr, $post_ID ) { $html = str_replace( array("?","https://www.youtube.com/"), array("?rel=0&","https://www.youtube-nocookie.com/"), $html); return $html; }
Gleiche Höhe für Elemente
Als JS Datei `sameheight.js` speichern und einbinden:
jQuery(document).ready(function() { sameheightbox(); }); jQuery(window).resize(function() { sameheightbox(); }); function sameheightbox() { var highestBox = 0; jQuery('.sameheight').each(function(){ if(jQuery(this).height() > highestBox) { highestBox = jQuery(this).height(); } }); jQuery('.sameheight').height(highestBox); }
Einbinden z.B. mit:
add_action( 'wp_enqueue_scripts', 'wuk_sameheight', 5); function wuk_sameheight() { wp_enqueue_script( 'sameheight-js', get_stylesheet_directory_uri() . '/sameheight.js', array( 'jquery' ) ); }
Elemente welche die gleiche Höhe erhalten sollen dann die CSS Klasse sameheight geben.
Animierte GIF korrekt ausgeben
add_filter('post_thumbnail_size','gif_alwaysfull',999,2); function gif_alwaysfull($size, $postid) { $thumb_low = get_the_post_thumbnail_url(); if (strpos($thumb_low, '.gif') === false) { return $size; } else { return 'full'; } }
Author/Tag/Kategorie Archivseiten deaktivieren (WordPress)
add_action('template_redirect', 'wuk_custom_removepage'); function wuk_custom_removepage() { global $wp_query; if( is_category() || is_tag() || is_date() || is_author() ) { $wp_query->set_404(); } }
xmlrpc.php deaktivieren
add_filter( 'xmlrpc_enabled', '__return_false' );
Automatische Updates aktivieren/deaktivieren (WordPress)
Um alle Updates zu aktivieren:
add_filter('auto_update_core', '__return_true' ); add_filter('auto_update_plugin', '__return_true'); add_filter('auto_update_theme', '__return_true'); add_filter('auto_update_translation', '__return_true' );
Um alle Updates zu deaktivieren:
add_filter('auto_update_core', '__return_false' ); add_filter('auto_update_plugin', '__return_false'); add_filter('auto_update_theme', '__return_false'); add_filter('auto_update_translation', '__return_false' );
Natürlich lässt sich auch eine Kombination erstellen.
Diese Codes sollten im Child Theme oder einem Plugin untergebracht werden.
Bestellung auf Rechnung automatisch weiterverarbeiten (WooCommerce)
Bestellungen auf Rechnung bleiben normal immer auf „on hold“ hängen. Damit diese automatisch „Processing“ erhalten, muss folgender Code im Childtheme oder Plugin platziert werden:
add_action( 'woocommerce_thankyou', 'woocommerce_auto_processing_orders'); function woocommerce_auto_processing_orders( $order_id ) { if(!$order_id) return; $order = wc_get_order( $order_id ); if($order->has_status('on-hold')) { $order->update_status( 'processing' ); } }
Dieser Code setzt alle Bestellungen automatisch auf processing. Wenn man will, kann man auch prüfen ob die Bestellung per „bacs“ gemacht wurde (Rechnung).
Mailreminder für Bewertung nach 14 Tagen (WooCommerce)
Es wird das Trusted Shop Template von Germanized missverwendet.
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', 'handle_custom_query_var', 10, 2 ); function handle_custom_query_var( $query, $query_vars ) { if ($query_vars['remindersend'] == '0') { $query['meta_query'][] = array( 'key' => '_reminder_email_sent', 'compare' => 'NOT EXISTS' ); } return $query; } if (!wp_next_scheduled( 'reminder_cron_hook' ) ) { wp_schedule_event( strtotime('09:30:00'), 'daily', 'reminder_cron_hook' ); } add_action( 'reminder_cron_hook', 'reminder_cron_function' ); function reminder_cron_function() { $remindernachtagen = 14; $bis = time() - ($remindernachtagen * 86400); $von = $bis - (14 * 86400); $args = array( 'status' => 'wc-completed', 'date_completed' => date("Y-m-d",$von).'...'.date("Y-m-d",$bis), 'return' => 'ids', 'remindersend' => '0' ); $orders = wc_get_orders( $args ); $allmails = WC()->mailer()->emails; $email = $allmails['WC_TS_Email_Customer_Trusted_Shops']; foreach ($orders as $order_id) { $email->trigger( $order_id ); $order = wc_get_order( $order_id ); $order->update_meta_data( '_reminder_email_sent', '1' ); $order->save(); } }
Nur kostenlose Lieferung wenn möglich (WooCommerce)
Wenn mehrere Versandmöglichkeiten möglich sind, aber kostenloser Versand verfügbar ist, wird alles entfernt und automatisch kostenlos verschickt:
add_filter( 'woocommerce_package_rates', 'wuk_hide_shipping_when_free_is_available', 100 ); function wuk_hide_shipping_when_free_is_available( $rates ) { $free = array(); foreach ( $rates as $rate_id => $rate ) { if ( 'free_shipping' === $rate->method_id ) { $free[ $rate_id ] = $rate; break; } } return ! empty( $free ) ? $free : $rates; }
Strasse ohne Hausnummer Warnung (WooCommerce)
Wenn keineHausnummer bei der Adresszeile eingegeben wird,wird eine einmalige Warnung ausgegeben um dies zu korrigieren.
add_action('woocommerce_checkout_process', 'address_field_validation', 10, 0); function address_field_validation() { if ($_POST['billing_address_1'] && ! preg_match( '/[0-9]+/', $_POST['billing_address_1'] ) && (!isset($_SESSION['oncehausnummer']) OR $_SESSION['oncehausnummer'] <= (time()-120))) { $_SESSION['oncehausnummer'] = time(); throw new Exception( sprintf( __( 'Bei der Strasse wurde keine Hausnummer gefunden. Bitte geben Sie diese an, falls Sie eine besitzen. Besitzen Sie keine, können Sie einfach nochmals zu Schritt 2 weitergehen.', 'woocommerce' ) ) ); } }
Checkout Felder entfernen die ungewünscht sind und Anpassungen (WooCommerce)
Entfernt Kanton und 2te Adresszeile:
add_filter( 'woocommerce_default_address_fields' , 'wuk_remove_checkout_fields2' ); function wuk_remove_checkout_fields2( $fields ) { unset($fields['address_2']); unset($fields['state']); $fields['postcode']['class'] = array('address-field','form-row-first'); $fields['city']['class'] = array('address-field','form-row-last'); return $fields; } add_filter( 'woocommerce_checkout_fields' , 'wuk_remove_checkout_fields' ); function wuk_remove_checkout_fields( $fields ) { unset($fields['billing']['billing_address_2']); unset($fields['billing']['billing_state']); unset($fields['shipping']['shipping_address_2']); unset($fields['shipping']['shipping_state']); $fields['billing']['billing_postcode']['class'] = array('form-row-first'); $fields['billing']['billing_city']['class']= array('form-row-last'); $fields['shipping']['shipping_postcode']['class'] = array('form-row-first'); $fields['shipping']['shipping_city']['class']= array('form-row-last'); return $fields; }
Autoresponder per Code abschalten (Enfold)
add_filter( 'avia_contact_form_args', 'no_enfold_autoresponder',80); function no_enfold_autoresponder($form_args) { $form_args['autoresponder'] = false; $form_args['autoresponder_subject'] = ''; $form_args['autoresponder_email'] = ''; $form_args['autoresponder_reply_to'] = ''; return $form_args; }
Visueller Editor von Enfold bei Custom Post Types aktivieren
add_filter('avf_alb_supported_post_types', 'wuk_visualeditor_for_post_types', 10, 1); function wuk_visualeditor_for_post_types( array $supported_post_types ) { $supported_post_types[] = 'dein-post-type'; return $supported_post_types; }
CPT in allen Enfold Elementen nutzbar
Im Childtheme einfügen:
add_theme_support('add_avia_builder_post_type_option'); add_theme_support('avia_template_builder_custom_post_type_grid');
Enfold Formular Conversion Tracking
Beispiel für Google Ads:
add_filter('avf_contact_form_submit_button_attr','avia_add_submit_attributes_to_cf', 10, 3); function avia_add_submit_attributes_to_cf($att, $formID, $form_params){ $att = "onclick=\"gtag('event', 'conversion', {'send_to': 'AW-942730802/sddUCP_7tGYQstzDwQM'});\""; return $att; }
Beispiel für Linkedin:
add_filter( 'avia_contact_form_args', 'change_enfold_success_msg'); function change_enfold_success_msg($form_args, $post_id='') { $form_args['success'] = str_replace( "</h3>", '<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=..." /></h3>', $form_args['success'] ); return $form_args; }
Menüzeile früher umbrechen (Enfold)
@media only screen and (max-width: 1350px) { #top #header .av-main-nav > li > a { font-size: 18px !important; } } @media only screen and (max-width:1270px) { #top #header .av-main-nav > li > a { font-size: 16px !important; } } @media only screen and (max-width:1200px) { #avia-menu .menu-item { display: none; } #avia-menu .av-burger-menu-main { display: block; } #avia-menu { width:auto !important; float:right: !important; } }
Icons in Trennzeilen grösser machen (Enfold)
.av-seperator-icon { display: inline-block; vertical-align: middle; font-size: 40px; line-height: 50px; }
Enfold Topbar höher machen
#header_meta, #header_meta .container { min-height: 36px; } #header_meta .sub_menu { font-size: 16px; } #header_meta .sub_menu li { line-height: 16px; } #header_meta .phone-info { font-size: 16px; padding: 9px 0 0 0; font-weight: normal; } #top #wrap_all .social_bookmarks { margin-top: 2px; } #header_meta .sub_menu>ul>li>a, .sub_menu>div>ul>li>a { font-weight: normal; }
Enfold Gallerie kein Hover Effekt
#top .avia-gallery .avia-gallery-thumb a:hover { opacity: 1; }
Sprachleiste mit DE | EN statt Flaggen (WPML)
.avia_wpml_language_switch li .language_flag { display: none; } .avia_wpml_language_switch li .language_code { display: block; text-transform: uppercase; } .avia_wpml_language_switch {top: 0px; padding: 0; } #top ul.avia_wpml_language_switch li { padding: 0 10px !important; border-right-style: solid !important; border-right-width: 1px !important; } #top ul.avia_wpml_language_switch li:last-child { padding: 0 10px !important; border-right-style: none !important; border-right-width: 0 !important; }
Enfold Untermenü breiter machen
.av-main-nav ul { width: 308px; }
Ampersand (&) normal machen
.special_amp { color: inherit !important; font-family: inherit; font-size: inherit; }
Conversion Tracking (Contact Form 7)
function gtag_report_conversion(url) { var callback = function () { if (typeof(url) != 'undefined') { window.location = url; } }; gtag('event', 'conversion', { 'send_to': 'AW-.../...', 'transaction_id': '', 'event_callback': callback }); return false; } document.addEventListener( 'wpcf7mailsent', function( event ) { gtag_report_conversion('<?php echo get_the_permalink(); ?>'); }, false );
Rechte Maustaste deaktivieren
if (document.addEventListener) { document.addEventListener('contextmenu', function(e) { e.preventDefault(); }, false); } else { document.attachEvent('oncontextmenu', function() { window.event.returnValue = false; }); }
Firefox unscharfe Bilder wenn verkleinert Korrektur
img { image-rendering: auto; }
Silbentrennung per CSS
Web Silbentrennung aktivieren:
@supports (hyphens: auto) { body { hyphens: auto; -webkit-hyphens: auto; -webkit-hyphenate-limit-chars: auto 3; -webkit-hyphenate-limit-lines: 4; -ms-hyphens: auto; -ms-hyphenate-limit-chars: auto 3; -ms-hyphenate-limit-lines: 4; } }
Nicht alle Geräte unterstützen dies.
Wenn man wuk.ch offen hat und ein anderen Tab öffnet, dann ändert der Tab den Titel automatisch hin und her und generiert wo Aufmerksamkeit zum Zurückommen. So können USPs oder Botschaften eindrücklich übermittelt werden.
Dazu ist nur ein Javascript nötig. Dieses Script nutzt jQuery.