Vendor Lock-in, het digitale Waxinelichtje?

De wereld om ons heen wordt alsmaar digitaler. Langzaamaan verdwijnen beroepen als archiefbeheerder en worden deze vervangen door een meer tech savy recordmanager en zie je door de automatisering steeds minder lopende band medewerkers. Ondanks de impact die dit op diverse individuen en gezinnen zal hebben biedt het voor het gros van de mensen en in het dagelijks leven vele (onopgemerkte) voordelen.

De Cloud

Een van deze voordelen is dat steeds meer van je data altijd èn overal toegankelijk is, het compromis dat we op dit vlak qua privacy inleveren lijkt velen van ons nauwelijks te deren en hoe goedkoper we onze data ïn de cloud” kunnen zetten, hoe liever we dat doen, niet volledig bewust van het feit dat we onderaan de streep hier echt wel een verdienmodel mee in de kaart spelen voor allerhande bedrijven.

Ondergetekende beseft zich dat zo’n beetje heel z’n tienerjaren met de teloorgang van Hyves ten onder zijn gegaan>

Echter hebben we niet door dat we meer en meer afhankelijk worden van deze grote, al dan niet machtige bedrijven, echter lijkt dit op het eerste oog misschien niet zo heel ingrijpend. Want hoe erg mis je de foto’s en emotionele verhalen die je op Hyves deelde nou werkelijk (ondergetekende beseft zich dat zo’n beetje heel z’n tienerjaren met de teloorgang van Hyves ten onder zijn gegaan waardoor ik vrijwel geen “tastbare” herinneringen aan deze fase heb), maar we vertrouwen ook onze volledige e-mail geschiedenis toe aan partijen als Google en Microsof. Bovenstaande voorbeelden zijn echter relatief eenvoudig nog redundant op te slaan door af en toe een back up te maken of belangrijke zaken ouderwets uit te printen / te downloaden en op een “betrouwbare plek” op te archiveren.

Streamen

Maar doordat zaken als cloud opslag zo’n gemeengoed zijn geworden, zijn we er langzaamaan ook gewend aan geraakt om daadwerkelijke voor dergelijke niet tastbare zaken te betalen. Niet langer verkopen we enkel onze privacy maar sluiten we met liefde abonnementen af om muziek en films te kunnen streamen. Niet langer bouwen we aanzienlijke collecties van collector’s editions met handtekeningen van de artiest op maar gaan we voor de onzichtbare oplossing en het gemak welke na 1 keer kijken / luisteren vervlogen kan zijn terwijl de kosten ervoor maandelijks terugkeren. Ook dit is niet iets dat enkel van deze tijd is, want ook de leesmap en videotheek waren voorbeelden van entertainment welke we enkel mochten consumeren en niet mochten houden.

Gevoelige informatie

Toch moet ik opmerken dat ik het ergens wel vreemd vind dat we (ik vorm hierop geen uitzondering) ‘vanuit veiligheidsoverweging’, vrijwillig en tegen betaling onze gebruikersnamen en wachtwoorden ergens op een externe omgeving plaatsen waarvan we geen of ten minste beperkt zicht hebben op de idealen van deze bedrijven die zich als wachtwoordmanager profileren. Los van het veiligheidsrisico wat, zo heeft de tijd ons geleerd, niet echt in het geding lijkt te zijn, maak je jezelf volledig afhankelijk van de wachtwoordmanager van jouw keuze. Mocht een van de diensten in zwaar weer verkeren, is het niet zo onschuldig dat je niet langer je favoriete muziek, of film niet kunt bekijken of beluisteren, maar verlies je in potentie de toegang tot al je accounts wanneer de dienst waar jij jouw wachtwoorden aan toevertrouwt zou verdwijnen.

Bewaren

Tot nu toe gaat het hierboven vooral nog over dienstverlening, je betaald abonnementskosten om van bepaalde extern beschikbare data gebruik te mogen maken afhankelijk van de de looptijd van je betaling of beschikbaarheid van de content. Maar ook het “verslavende aspect” waarbij je op den duur in meer of mindere zin afhankelijk wordt van de geleverde diensten of naast de opslag van jouw wachtwoorden, ook jouw persoonlijke of zakelijke foto’s of bestanden enkel nog online hebt “bewaard”. Echter zorgt dit er ook voor dat je zo afhankelijk wordt van de desbetreffende dienst dat je bereid bent er een hoge prijs voor te betalen om maar niet de moeite te hoeven doen alles over te hevelen, oftewel “Vendor Lock-in”, je wilt, of kunt niet meer zonder de dienst.

Fysieke producten

Waar ik mezelf laatst echter ook op betrapte is dat het niet alleen deze dienstverlening is. Steeds vaker zie je smart devices de revue passeren. Ieder apparaat lijkt tegenwoordig wel connected te moeten zijn en “the Internet of Things” is real! Ook hier zijn de gemakken niet uit de lucht maar als ik alleen al naar mijn muziek behoefte kijk heb ik voor honderden euro’s aan Sonos apparatuur staan welke bij het faillissement van Sonos en / of het offline gaan van haar serverpark totaal onbruikbaar worden. Sterker nog, als ik besluit niet langer te willen betalen voor mijn maandelijkse Spotify abonnement verliezen deze boxen vrijwel al haar waarde. En ook hier zou bijv. Sonos er zelf nog voor kunnen kiezen om je naast je streaming abonnementen ook nog een extra fee te heffen om van de Sonos infrastructuur gebruik te mogen maken. Ethisch valt hier natuurlijk wat over te zeggen, maar als je er al €1.000,- of sommige zelfs vele malen meer, in hebt zitten zul je toch al snel geneigd zijn toch ‘die paar euro per maand’ over te maken om je boxen te kunnen blijven gebruiken.

Smart Home

Hoewel ik meer en meer bewust geen “Smart Home” inricht, heb ik zeer zeker een “Connected Home”. Ook hierin ben ik echter steeds afhankelijker van beschikbaarheid en ondersteuning van diensten van derden. Mijn verlichting is voor 70% gegijzeld door Trust en haar KlikAanKlikUit. Hoewel het hier voor een steeds groter deel met Zigbee LL een “open standaard” betreft, kan ik de Octopus in mijn meterkast die de signalen naar de diverse apparaten niet meer bedienen wanneer de App uit de Play Store wordt teruggetrokken.

Al deze zaken waaraan ik langzaam aan gewend raak en die stiekem, hoewel volstrekt overbodig, toch erg handig zijn, kunnen ieder moment verdwijnen.

Bovenop het KlikAanKlikUit Octopus Control Center heb ik nog Olisto hangen, een startup welke een spil in het web wil worden tussen de verschillende smart devices. Door mij voor nu nog vooral gebruikt om de kleur van mijn lampen te veranderen als er wordt gescoord, of ter indicator dat mijn afval naar buiten moet en daarbij dan een corresponderende kleur geeft (waarbij ik ook weer afhankelijk ben van een zelf geschreven integratie met de API van AfvalWijzer). Maar ook is dit een van de weinige “slimme oplossingen” welke bepaalde lampen (tijdelijk) inschakelt op basis van mijn wekker en de actie waarbij ik mijn telefoon van het nachtkastje haal. Al deze zaken waaraan ik langzaam aan gewend raak en die stiekem, hoewel volstrekt overbodig, toch erg handig zijn, verdwijnen wanneer Olisto uit de lucht zou gaan of niet langer wenst te koppelen met de systemen van Trust.

Dan is er nog mijn Logitech Harmony Afstandsbediening, welke, (gelukkig?) volledig offline werkt. Deze kan ik blijven gebruiken binnen mijn huidige Home Theater Setup, zelfs als Logitech besluit haar dienstverlening omtrent de Harmony lijn te staken. Echter is mijn TV en alle randapparatuur naar alle waarschijnlijkheid niet het eeuwige leven beschoren. Wanneer ik een nieuw apparaat wil kunnen bedienen met mijn Universele Afstandsbediening dan moet ik hiervoor de Software van Logitech raadplegen welke op haar beurt weer gebruik maakt van de IR code database waarin Logitech alle ondersteunde apparaten online, ofwel, “in de cloud” heeft opgeslagen.

De nieuwste telg in mijn huis is een “Blind Engine” van de voor mij onbekende fabrikant Brunt, een motortje dat ervoor zorgt dat mijn rolgordijn open en dicht gaat. Keurig verbonden met Alexa en Google Assistant, welke op hun beurt een verzoek naar de servers van Brunt in Korea sturen welke er vervolgens via WiFi voor zorgt dat dit motortje in actie komt, je raadt het al, als deze servers verdwijnen of voor kwaadaardige doeleinden gebruikt worden…..

Voice Assistants, waar houdt het op?

Daar houd het echter niet op, de laatste tijd zien we met de opkomst van Google’s Home Assistant dat velen Google inzicht geven in allerhande online data. Van op het eerste gezicht onschuldige zaken als de AH Bonuskaart om hun boodschappenlijstje met een stemcommando aan te kunnen vullen tot toegang tot je bank om je saldo via Google op te kunnen vragen.

Wat als Google de informatie van je saldo gaat koppelen aan Google Shopping en (nog meer) getarget prijsverhogingen en aanbiedingen uitzet of juist intrekt op basis van je inkomen. Want, als ze op jouw verzoek je saldo in kunnen zien, kunnen ze ongetwijfeld ook de exacte datum van je salaris uitbetaling en hoogte van dit salaris inzien. Het schijnt zelfs zo te zijn dat ING inmiddels bezig is om direct betalingen via de Google Assistant uit te kunnen voeren, herkent hij dan echt enkel jouw stem, of kan Jan en alleman in de buurt van jouw telefoon of Google Home apparaat diverse gelden ten gunste van zichzelf overboeken?

Hoewel ik veel technologie met open armen ontvang en er gretig gebruik van maak zijn het dit soort momenten van reflectie die ervoor zorgen dat ik de ontwikkelingen met argusogen aanschouw terwijl ik er gretig gebruik van maak. De tegenstrijdigheden in mij vieren hoogtij wanneer ik bewust stil sta bij mijn eigen gebruik. Voor nu vergelijk ik het maar met een waxinelichtje. Iedereen heeft ze (weleens) in huis en jaarlijks gaan er meerdere zakken doorheen, super gezellig natuurlijk, maar heb je er echt iets aan, of is het eigenlijk een minimale vorm van kapitaalvernietiging waar we (makkelijk) zonder kunnen, maar dat al lang niet meer willen.

Waar houdt het op?

Simpele aanpassingen die je E-mail headers optimaliseren tegen Spam

Het versturen van e-mail vanaf een eigen server is altijd een “dingetje” geweest.

Een aantal factoren zullen negatief van invloed zijn op ongewenste e-mail filters op server en applicatie niveau.

  • Standaard zal jouw website waarschijnlijk gehost worden op een zogeheten “shared hosting omgeving”, waar niet alleen jouw website, maar ook tientallen andere uiteenlopende websites gehost zijn. Er zullen dan vanaf het desbetreffende IP adres niet alleen door jouw website e-mails worden verzonden, maar ook de andere websites sturen e-mails uit vanuit hetzelfde IP adres
  • Als je relatief veel e-mails met soortgelijke opbouw en content verzend kan de kans bestaan dat het eerder wordt aangemerkt als een ‘mail bom’, echter als jouw website bijvoorbeeld beschikt over een reserveringsmodule of betaal- en verzendnotificatie mails kun je hier niet omheen, buiten de naam en reserveringsdatum / aankoopgegevens kan de rest van de getoonde informatie in deze e-mails identiek zijn.

Met onderstaande tips heb ik in het verleden succesvolle resultaten geboekt waarmee e-mails minder snel in de ongewenste e-mail folder belanden. Helaas berust dit op mijn eigen ervaringen en hoeft dit geen garanties te bieden dat dit voor jouw case ook het geval is. Zelf heb ik in de Mail-Tester circa 4 punten winst weten te behalen wat de mails daarnaast tevens van de ongewenste e-mail folder naar de inbox wist te verhuizen in diverse Microsoft Office 365 omgevingen. Dit heb ik bereikt door enkel de SPF Records en het ‘Return-Path’ aan te passen, hopelijk kun jij door het toepassen van deze tips soortgelijke resultaten bewerkstelligen.

E-Mail Service

Laten we maar gelijk met de deur in huis vallen, idealiter verstuur je je e-mails niet vanaf een (shared) hosting. De kans is groot dat dit IP Adres door meerdere domeinen (in het verleden) wordt gebruikt waardoor de markering van deze server niet ideaal is. Ook ben je bij het versturen van honderden mails per dag sowieso al snel een “Red Flag” voor Spam filters en kan het optimaliseren van de load om deze pieken te spreiden, of verdere server aanpassingen om netter met uit te sturen mails om te gaan al snel tijdrovend worden.

Als het versturen van bevestigingsmails, notificaties of eender andere mail oplossing een van je core activiteiten is, zou ik aan willen raden om eens te kijken of een E-mail service zoals Mailgun of Amazon SES niet beter geschikt is voor jouw doeleinde, hier zijn echter wel kosten aan verbonden. Mocht je sporadisch een mail versturen of het toch willen proberen, lees dan gerust verder.

SPF – Sender Policy Framework’

SPF staat voor ‘Sender Policy Framework’, iets dat ik voor het schrijven van dit bericht ook nooit uitgeschreven had gezien terwijl ik het toch al enige tijd toepas. Wat ik door ervaring wel weet over deze zogeheten SPF Records is dat ze eigenlijk onmisbaar zijn in de DNS Records van jouw domeinnaam. Nou kan ik hier een heel betoog gaan afsteken over wat SPF precies inhoud en welke parameters tot welk resultaat kunnen leiden. Echter zoals eerder aangegeven ben ik geen DevOps en is er genoeg te vinden over SPF Records waardoor ik het voor nu hou op 2 relatief simpele voorbeelden welke voor mij tot het beoogde resultaat hebben geleid.

Het meest simpele voorbeeld is, stel dat het domein *.doe.com mails verstuurd vanuit IP Adres “192.168.1.1” dan stel je deze als volgt in:

v=spf1 a ip4:192.168.1.1 ip6:::ffff:c0a8:101 -all

Het 2de voorbeeld heb ik toegevoegd omdat in het gros van de gevallen waar ik het de laatste tijd nog mis zie gaan, Microsoft met haar Office 365 pakketten nogal streng blijkt te zijn in deze check. Eigenlijk kan het sowieso geen kwaad om dit toe te voegen aan je SPF Record, maar mocht je er zeker van zijn dat de ontvanger gebruik maakt van Office 365 dan is dit een must om aan je SPF Record toe te voegen.

v=spf1 a ip4:192.168.1.1 ip6:::ffff:c0a8:101 include:spf.protection.outlook.com -all

Tip: zoals je ziet voeg ik ook gelijk het IPv6 adres van de server toe, ik heb al scenario’s gezien waarop spamfilters de check op IPv6 doen i.p.v. de oude, vertrouwde 127.0.0.1 achtige IP adressen.

Het Return-Path instellen

Op de perfect ingerichte webserver, zou je je hierover eigenlijk geen zorgen hoeven maken, maar mocht het je ontbreken aan een DevOps of draai je net als ik op een wat simpeler hosting pakket dan zijn er zaken die je wellicht in kunt stellen op PHP Niveau. Één van de zaken waarop ik veel winst heb weten te boeken is het zogeheten ‘Return-Path’. Dit is wat door de server ten aller tijden aan je mail wordt toegevoegd, zelfs als je bijv. in Contact Form 7 een ‘From:’ adres aangeeft kan er mailtechnisch gezien nog altijd iets staan als “Verzonden door John@Doe.com via returnpath@server.com”. Dit zorgt dus voor een conflict tussen wat jij ziet als afzender en de afzender vanuit de server, iets dat voor Spamfilters een behoorlijke “Red Flag” is als het gaat om de controle op ongewenste e-mails.

Ik ben toen gestuit op onderstaande code waardoor dit (in ieder geval in PHPMailer) is aan te passen zonder daarbij in je serverinstellingen te hoeven duiken. Deze code overschrijft de server afzender (returnpath@server.com, red.) door jouw (ingestelde) afzender (John@Doe.com, red.). Iets wat in mijn tests naast het SPF record een van de grootste winsten opleverde.

/**
 * Attempt to override Return-Path
 *
 * @author: Simon
 * @date: 14-3-2018
 * @url: http://Simon.vdSteen.me/WordPress/e-mail-headers-optimaliseren-tegen-spam
 */
add_action( 'phpmailer_init', function( $phpmailer ) {
    $phpmailer->Sender = $phpmailer->From;
} );

DKIM – DomainKeys Identified Mail

Als laatste wil ik DKIM dan nog even toelichten, zelf heb ik mij hier nooit in verdiept omdat hier extra verificatie en configuratie bij komt kijken, maar mocht je met bovenstaande optimalisaties geen winst in het aantal afgeleverde mails bereiken dan kan dit de moeite zijn om eens in te duiken.

Bij het gebruik van DKIM genereer je ‘keys’ waarmee je de echtheid van je mails waarborgt, middels deze ‘keys’ (een ‘private key’ op jouw server en een ‘public key’ in een DNS Record) leg je een relatie tussen de server waar je de mails vandaan stuurt en de DNS van het domeinnaam. Vervolgens controleert de ontvangende mailserver op basis van de ingestelde ‘selector’ of de versleutelde header uit de mail overeenkomt met de ‘key’ in het DNS Record, waardoor de authenticiteit van de verzendende server kan worden gewaarborgd.

Mail-Tester

Wanneer je bovenstaande optimalisaties hebt doorgevoerd, is het tijd om te testen. Dit doe ik in dit geval door het gebruik van Mail-Tester

De slogan van Mail-Tester is: “Test de Spamyness van je emails”. Deze dienst is opgezet door de ontwikkelaars achter MailPoet en AcyMailing. Hoewel ook zij met hun jarenlange ervaring geen garanties kunnen geven dat jouw e-mails überhaupt aankomen, is het een goede eerste indicatie van de kwaliteit van jouw e-mail headers en de relatie tussen server en DNS instellingen. Indien zelfs Mail-Tester jouw e-mail headers al met een 1.2 beoordeelt kun je er vrij zeker van zijn dat de kans dat jouw berichten ooit het daglicht zullen zien relatief laag is. Mail-Tester geeft een goede eerste indicatie omtrent het technische niveau van de e-mails die vanuit jouw WordPress website worden gegenereerd.

Dus naast het testen of de mails goed in jouw mailbox aankomen, stel ik ten aller tijden voor om na livegang ook een test e-mail naar een Mail-Tester e-mailadres te sturen om te kijken of er nog verbeterpunten zijn. Dit doe je door te surfen naar https://www.mail-tester.com/ en het hier aangeduide e-mail adres in het afleverveld van je contactformulier te plaatsen.

Google Assistant voor diensten zonder Google Home ondersteuning

Hoewel het, in veel situaties nog ongemakkelijk is om een digitale personal assistent te gebruiken, moest Google na de introductie van Apple’s personal assistent haar meerdere erkennen in Siri en met daarbovenop de komst van Amazon’s Alexa was Google Now te beperkt gebleken. Inmiddels heeft Google haar Google Assistant (met een workaround, voor nu nog geen Nederlands variant, dus ik doe het met de Engelse variant) beschikbaar gesteld op alle Android toestellen.

Hoewel ik mij prima weet te reden in de Engelse taal, maakt het de drempel nog hoger om “ineens” in het luchtledige Engels te praten, maar voor mijn basis “Smart Home” behoeften (OK Google, Lights on, OK Google, Lights off, OK Google, Shut down, red.) was dit prima toereikend.

Home Control

Google biedt, net zoals Apple’s HomeKit een API aan om spraakopdrachten vanuit Google’s Assistant om te zetten naar activiteiten in jouw Domotica software. Hoewel hier naast een 50 tal Amerikaanse aanbieders ook ‘Philips Hue’ en ‘Honeywell’ in te vinden zijn, blijft het aanbod hierin voor nu nog beperkt en is het nog niet mogelijk om bijvoorbeeld ‘KlikAanKlikUit’, of ‘Nest’ apparatuur aan te sturen. Echter valt dit met de tussenkomst van ‘IFTTT’ en ‘Triggi’ te verhelpen.

If ‘Google Assistant’ Then ‘Webhooks’

We gebruiken dus niet Google’s eigen, ‘Home Control’ koppeling, maar willen met onze spraakopdrachten IFTTT aansturen. Het nadeel van dit IFTTT Recipe is dat je geen gebruik kunt maken van standaard ‘phrases’ als “OK Google, Lights on” en “OK Google, Lights off“, deze zijn namelijk door Google gereserveerd voor gebruik met “Home Control” en geven bij het niet instellen van een “Home Control” dienst de melding: “It looks like those lights haven’t been set up yet.”.

In het begin baalde ik hiervan, maar al snel heb ik dit opgelost door deze ‘phrases’ vooraf te laten gaan door een van de bekende “Artificial Intelligence” systemen uit de filmgeschiedenis.

Op deze manier wordt het dus, “OK Google, Yarvis, Lights on“, of “OK Google, KITT, Lights off“. In het begin voedt dit de “inner nerd” maar uiteindelijk wint het gemak het toch van deze gimmick en kijken vrienden je toch minder raar aan als je gewoon “OK Google, Lights on” zegt.

Google Assistant Shortcuts

Per toeval kwam ik in de instellingen van de ‘Google Assistant’ App tot de ontdekking dat je ook zogeheten Shortcuts kan toekennen. Hier kun je per ‘phrase’ een 5 tal ‘shortcut phrases’ uitschrijven welke dan een custom ‘phrase’ triggeren in ‘Google Assistant’. Toen ik aan het experimenteren was met het gebruiken van Nederlandstalige zinnen kwam ik er zelfs achter dat je via deze ‘shortcuts’ ook de “gereserveerde zinnen” zoals “OK Google, Lights on” en “OK Google, Lights off“, voor het gebruik van bijv. ‘Home Control’ kan overschrijven.

Middels onderstaande werkwijze is het dus mogelijk om de versimpelde gereserveerde Engelstalige ‘phrases’ te gebruiken om je lichten met een dienst van jouw keuze (via bijv. ‘IFTTT Webhooks’ en Triggi) te schakelen.

  1. Tik op je telefoon op de startknop en houd deze vast.
  2. Tik in de rechterbovenhoek op  en vervolgensMeer en vervolgens Settings and then Shortcuts
  3. Tik in de rechteronderhoek op +
  4. Voer bij When I say Ok Google… je ‘phrase’ in, bijv. “Lights on” (dus zonder, OK Google)
    1. Een nieuw invoer Or when I say Ok Google… verschijnt en hier kun je tot 5 gesproken commando’s toevoegen
  5. Voer bij Google Assistant should do de “technische” Engelsetalige ‘phrase’ in die je in IFTTT (of een andere app die toegang heeft tot de Google Assistant SDK hebt ingesteld), in mijn geval “Yarvis, Turn the lights on
  6. Tik in de rechterbovenhoek op Save

Dat is alles. Vanaf nu kun je de aangepaste spraakcommando’s gebruiken om je “Smart Home” te bedienen of andere “Connected devices” aan te sturen.

“Nederlandse” Shortcuts

Hoewel je via bovenstaande methode in theorie Nederlandse Shortcuts kan definieren en deze ook werken bij de tekstgestuurde variant van Google Assistant waarbij je zelf de zinnen zelf uittypt i.p.v. deze middels spraak in te voeren. Kan de huidige Google Assistant spraakcommando’s in het Nederlands niet alleen niet ‘begrijpen’, maar ook niet ‘verstaan’. Wanneer je “OK Google, Licht aan” probeert, zal Google Assistant dit interpreteren als lift, list of lyft. Bij het gebruik van jouw eigen stem kunnen deze resultaten natuurlijk weer anders zijn. Dit wijkt dusdanig ver af dat het lastig is om hier ‘shortcuts’ voor te definieren.

Echter zijn er een aantal woorden die wel / beter door de Engelstalige variant van Google Assistant worden ‘verstaan’. Zaken als ‘lampen’ of ‘slapen’ hebben in mijn geval redelijk succes, maar worden door de Google Assitant nog altijd niet ‘begrepen’ waardoor automatisch een zoekopdracht geprobeerd zou worden. De woorden aan en uit worden helaas ook niet ‘verstaan’ door de Google Assistant, in mijn geval worden deze echter redelijk structureel vertaald naar respectievelijk on / and en out / at.

Wanneer je deze woorden als Nederlandstalige ‘shortcuts’ toevoegd en koppelt aan een bekende Engelstalige ‘phrase’ als “Yarvis, Turn the lights on” welke binnen IFTTT is geconfigureerd kun je de Google Assistant beperkt in het Nederlands aansturen. Met maximaal 5 snelkoppelingen per ‘phrase’ (uit te breiden naar een oneindig aantal keer 5 voor dezelfde ‘phrase’) kun je de alledaagse aansturing toch in het Nederlands realiseren.

 

 

Hello Cache! Het praktisch nut van de WordPress Transients API

Eerder sprak ik al over de 7 zonden uit mijn carrière als developer, vandaag grijp ik terug op weer een kritiek puntje dat zich hieronder schaart. Lange tijd keek ik met een lange neus naar elke technologie die eender welke manier van Cache behelsde. Ik wilde de data die ik op mijn website publiceerde, live tonen zonder enige compromis. Wanneer je slechts een paar bezoekers bediend, is er geen vuiltje aan de lucht en ligt de data of dienst er in het ergste geval (na verloop van tijd) een keer uit waardoor er geen informatie kan worden getoond. Echter zodra je website wat meer traffic genereert kan het zijn dat je het aantal API calls overschrijd, maar het echte verschil werd voor mij merkbaar tijdens mijn werkzaamheden bij INDICIA en Dutchwebdesign waarbij klanten werden bediend met grotere belangen, bredere doelgroepen en meerdere (gelijktijdige) bezoekers. Op dat moment bedacht ik me, wellicht is het helemaal niet logisch om voor elk individu alle data live op te halen.

Wellicht is het helemaal niet logisch om voor elk individu alle data live op te halen.

Toch heeft het tot een interessante talk van Andreas Creten op WordCamp Antwerp 2016 geduurd alvorens ik enigszins geënthousiasmeerd raakte tot het gebruik van Caching, of in ieder geval de denkwijze achter Caching. Mijn ervaringen met Cache tot dat moment waren beperkt tot zogeheten “alles of niets” configuraties waardoor elke webpagina, elke vorm van dynamiek verloor en enkel (verouderde) statische content toonde. Iets wat natuurlijk geen optie is voor een Social Media feed, “Now Playing” koppeling met Spotify of “Last Beer” verwijzing vanuit Untappd.

Uiteraard zijn er zat mensen die zich hebben gespecialiseerd in Cache en zijn hier veel bredere, interessantere en diepgaandere posts over te vinden. Ook zal er een andere groep zijn die roept dat al je Caching debakels opgelost zijn door het installeren (en in mijn beleving ondergeschoven, maar niet onbelangrijk, juist configureren) van Cache plugins als W3TC en WP Super Cache. Deze laatste optie kan voor een informatieve website die weinig actueel is met een simpele basisconfiguratie een prima snelheidswinst bewerkstelligen. Maar dit komt vooral doordat zaken als het menu, de footer en voor jou belangrijke pagina’s als “over ons” en “contact” over het algemeen weinig zullen veranderen. Uit mijn eigen persoonlijke ervaring is echter gebleken dat dynamische content als live feeds met data uit bijvoorbeeld Social Media platformen of externe API's niet zo vanzelf sprekend zijn bij een basisconfiguratie en je hier echt wel wat aanpassingen aan de configuratie, Codebase of zelfs de Server moet verrichten zodat deze data zich ververst wanneer jij dat wenselijk acht, i.p.v. meerdere dagen achtereenvolgend een statisch karakter aan te nemen.

Hoewel het beheersen van de diverse lagen van Cache op o.a. Browser en Server niveau niet tot mijn expertise behoort, probeer ik sindsdien aan de basis van het ontwikkelen van diverse koppelingen en grotere queries wel na te denken hoe realtime de data moet zijn. Bij een populair evenement kan het bijvoorbeeld van belang zijn dat je iedere 5 minuten de laatste Tweets en andere Social Media data op wil halen op je Social Wall, voor een Social Media feed van je eigen Facebook pagina kan een TTL (time to live, red.) van 6 uur volstaan, terwijl je voor een “meest bekeken videos” koppeling met YouTube een dagelijkse check toereikend kan zijn om het aantal keer dat een video bekeken is “lokaal” op te slaan.

Transients

Om het aantal databaseconnecties op je eigen server, of het aantal API requests te beperken ben ik gebruik gaan maken van de WordPress Transients API. Middels deze standaard beschikbare API kun je grotere queries eenmalig opslaan en het resultaat hiervan in zijn geheel wegschrijven naar één options achtige database entry. Op deze manier hoeft de database niet voor elke keer dat de query wordt aangeroepen een lookup langs de tabellen uit te voeren om het gewenste aantal rijen terug te geven. Het volledige resultaat van jouw query staat immers al compleet met alle relevante rijen voor een bepaalde tijd reeds opgeslagen in de enkele rij die door de Transient is opgeslagen.

Never trust a Transient!

Hoewel het een fijne gedachte is dat bepaalde data kant en klaar staat te wachten in je database of object (zie “Persistant Cache”). Mag je een transient nooit vertrouwen. Een transient is namelijk altijd van tijdelijke aard en hoewel de TTL nog niet verstreken hoeft te zijn, kunnen andere factoren er voor zorgen dat de transient toch al eerder uit de database of het object verdwijnt, denk hierbij aan een Cache Plugin die (al dan niet handmatig) alle Cache opschoont, of het geheugen dat volloopt waardoor de server besluit om de ruimte vrij te geven. Zorg er daarom altijd voor dat je controleert of de transient bestaat met get_transient(); en indien dit niet geval is je deze definieert in het statement met set_transient(); zodat op elk bekend is welke gegevens er moeten worden opgehaald en getoond.

Het code voorbeeld

Hieronder zie je dat er eigenlijk slechts 3 rijen bij komen, 2 voor het ophalen / definiëren van het if statement en 1 voor het wegschrijven van de transient. Alle overige code was sowieso al benodigd om op basis van de ID van de gewenste YouTube video, het aantal “views” op te kunnen halen middels een method die een verbinding maakt naar de YouTube API.

Je controleert eerst met get_transient(); of de transient die je nodig hebt nog bestaat en pas wanneer dit niet het geval is wordt de functionele code die je toch al geschreven hebt uitgevoerd en weggeschreven middels set_transient();. Wanneer de transient bestaat, wordt de get_transient(); toegekend aan de variabele $intViews en bevat deze dezelfde waarde als wanneer de functionele code zou worden uitgevoerd, met de kanttekening dat deze waarde wellicht wat verouderd is, in dit voorbeeld is dat maximaal 24 uur.

/**
 * Get a transient or refetch the data and recreate the transient that's alive for 24h.
 *
 * @author: Simon van der Steen
 * @date: 16-5-2017
 * @url: http://Simon.vdSteen.me/WordPress/cache-praktisch-nut-wordpress-transients-api
 */
$strYouTubeId = 'XXX-XXXXX';
$strTransientId = 'svds_youtube_views_' . $strYouTubeId;

//Check if saved transient exists.
if ( false === ( $intViews = get_transient( $strTransientId ) ) ) {
   //get_youtube_views() is a method to fetch data from the YouTube API.
   $intViews = get_youtube_views( $strYouTubeId );

   //Start of the extra code part which you might not need.
   $intSavedViews = get_post_meta( get_the_ID(), 'youtube_views', true );
   //Check if new value ($intViews) is bigger than the current value ($intSavedViews), else it could indicate that the API call went wrong. If false, the current meta value is re-set in the transient.
   if( $intViews > $intSavedViews ){
      update_post_meta(get_the_ID(), 'youtube_views', $intViews);
   }else{
      $intViews = $intSavedViews;
   }
   //End of the extra code part which you might not need.

   //Save the newly created transient so oncoming users can enjoy the data quicker.
   set_transient( $strTransientId, $intViews, DAY_IN_SECONDS );
}

//Output your transient data.
echo $intViews;

De reden dat ik in bovenstaand voorbeeld bovenop het opslaan van de transient tevens een nieuwe meta wegschrijf, is om deze waarde te gebruiken bij het sorteren van een “meest bekeken” video’s sectie. Dit is voor jouw oplossing wellicht geen vereiste en enkel het opvragen van de transient kan voor jouw casus toereikend zijn.

WP_Cron / save_post en Cache Warming

Een transient kan gebruikt worden om dynamische data “live” op te halen wanneer de bezoeker deze nodig heeft. Maar voor sommige taken kan het handig zijn om de transient alvast op te warmen voor het moment dat de bezoekers komen.

Mocht je data uit een externe API halen en tonen op jouw website, dan kan het zijn dat je deze data en bijbehorende assets in je eigen database wil opslaan zodat de bezoekers er acties op kunnen ondernemen of wellicht zelfs wijzigingen op aan kunnen brengen. Ook kan het zo zijn dat je simpelweg niet afhankelijk wil zijn van de externe partij waarbij data tijdelijk, of definitief verloren kan gaan, of dat je bang bent dat de externe server te kampen heeft met overbelasting. Je kunt deze data ophalen en wegschrijven op het moment dat de gebruiker de pagina bezoekt, maar dit veroorzaakt bij de eerste bezoeker toch een (lichte) vertraging en aangezien het “locking” mechanisme van de transients niet waterdicht is kan het zelfs zo zijn dat meerdere bezoekers die de site vrijwel gelijktijdig raadplegen dezelfde transient opnieuw aan het werk zetten nadat deze is verlopen waardoor één query meerdere keren wordt uitgevoerd en er een zwaardere server load of zelfs dubbele data gegenereerd wordt, dit kan er voor zorgen dat je database vervuild raakt en de gebruikerservaring drastisch verminderd doordat de performance van de server afneemt.

Om deze extra onnodige load en het wegschrijven van overbodige data te voorkomen, kan je er voor kiezen om de data middels een cronjob alvast voor je bezoeker op te halen op vooraf ingestelde tijden. Om dit te bewerkstelligen maak je gebruik van WP_Cron. Aan de methods die je binnen je cronjob uitvoert voeg je tevens een verwijzing naar je transient toe. Zo kun je er óf voor kiezen om de transient enkel te verwijderen met delete_transient();, zodat je garandeert dat de volgende bezoeker de meest recente data ophaalt zodra de cron is afgelopen. Óf je kiest er voor om de Cache alvast een beetje op te warmen door de method die de transient genereert uit te voeren zodra de cron is uitgevoerd. Op deze manier is de transient direct beschikbaar voor de eerst volgende bezoeker. Indien het hier om data gaat die niet heel vaak geraadpleegd zal worden is een cron of het vooraf vullen van de transient wellicht overbodig. Maar wanneer het om data gaat die bijvoorbeeld in je header of op de homepage geladen wordt, wil je misschien niet wachten tot de data een keer wordt opgehaald, maar wil je dat dit warme broodje klaar staat om door je bezoekers verorbert te worden.

Je zal Cache Warming niet ruiken, maar de snelheidswinst kan voor je bezoekers als een warm bad voelen.

In het verlengde daarvan kun je de regie ook wat meer in eigen hand nemen, voor zaken als een Social Wall die je niet vanuit je WordPress Backend beheert is dit wellicht niet ideaal, maar voor content die je vanuit de WordPress Backend genereert kan het handig zijn om deze klaar te zetten in een transient. Zo kan het handig zijn om op de wp_update_nav_menu hook het wp_nav_menu(); object of zelfs de gegenereerde HTML code voor het menu weg te schrijven in een transient. Het volledige menu kan dan worden geladen vanuit 1 database of object rij zonder daarbij alle menu items af in je database af te gaan en in je HTML te verwerken.

Persistant Cache

Hoewel de WordPress Transients API zich bij een standaard server zal beperken tot het gebruik van de database om de transients op te slaan, versterkt het gebruik van een Caching Plugin i.c.m. met een juist geconfigureerde server de manier waarop een transient zich gedraagt. Wanneer bijvoorbeeld gebruikt wordt gemaakt van memcache is de WordPress Transients API in staat dit waar te nemen en wordt gebruik gemaakt van WordPress Object Cache. In plaats van set_transient(); zal de WordPress Transients API gebruik maken van wp_cache_set(); waarbij een object op de server wordt aangemaakt en het verzoek aan de Database Server überhaupt niet hoeft te worden gemaakt. Waarschijnlijk kennen we allemaal de verschillen in snelheid bij het aanroepen van gegevens vanaf een harde schijf (zoals de Database Server zou doen) en direct uit het geheugen (wat het geval is bij het gebruik van bijvoorbeeld memcache. Op deze manier kun je de transients die je na het lezen van deze posts toch al in gaat richten, versterken en een nog grotere optimalisatie van de performance op je server bewerkstelligen.

WP_Query cached Post Meta

Hoewel dit niet direct in een relatie staat tot de WordPress Transients API, ben ik wel tot nieuwe inzichten gekomen aangaande Custom Fields. Ik wil deze bevindingen dan ook met jullie delen zodat jullie je niet blindstaren wanneer je na het gebruik van een transient voor een WP_Query(); object, het aantal gebruikte queries ineens toeneemt.

Het ophalen van een post plaatst alle relevante meta data in de cache.

Lange tijd maakte ik bij het ophalen van posts met een grote hoeveelheid Custom Fields gebruik van get_post_custom(); i.p.v. get_post_meta(); omdat ik dacht dat dit het aantal database requests aanzienlijk zou verminderen. Pas toen ik WP_Query(); objecten als transient ging opslaan, kwam ik er door het gebruik van Query Monitor achter dat bij het initiëren van het WP_Query(); object de Custom Fields behorende bij de zojuist opgehaalde posts (mits update_post_meta_cache  niet op false stond) automatisch in de wp_meta_cache werden weggeschreven en zonder additionele database connectie beschikbaar waren binnen de while loop.

“Cache” all the Things!

Ik hoop natuurlijk dat ik jou net zo heb kunnen enthousiasmeren als dat ik dat bij mijn eerste aanraking met de WordPress Transients API was en je gelijk met Caching en specifiek de WordPress Transients API aan de slag wil gaan. Ik zou jullie nu naast “Het code voorbeeld”, verder aan de hand mee kunnen nemen langs een basis inrichting voor je eerste transient. Echter zijn er al zat mensen met veel meer en onderbouwdere kennis dan dat ik heb. Hieronder heb ik dan ook de “Transient 101” video van gerenommeerde WordPress developer Pippins gedeeld zodat je direct aan de slag kunt.

Uiteraard is er met een juiste inrichting van diverse andere Caching technieken nog een hoop extra winst behalen. Maar je moet ergens beginnen, dus waarom in je toekomstige oplossingen niet alvast de voordelen van het gebruik van transients meenemen.

De Voordelen van de Pebble Time (Smart Watch)

Als een van de weinige, was ik al vroeg behoorlijk enthousiast over het nut van een Smart Watch. Een van de functionaliteiten die mij toch wel tot early adopter maakten waren de “fitness tracking” (realtime inzicht in de GPS data die Endomondo op je arm waarnam, red.) en de “play / pause” functionaliteit voor Spotify en Winamp (It really whips the llama’s ass!). Later kwamen daar “wrist notifications” en de mogelijkheid om je agenda raad te plagen vanaf je pols bij.

My First Sony

Mijn allereerste Smart Watch was een Sony Smartwatch 1 (MN2). Doordat ik na de “Ping” hype een fervent liefhebber geworden ben van BlackBerry, was ik beperkt in mijn keuze en was het vanaf BlackBerry OS 10 via het sideloaden van Android Apps uiteindelijk met de nodige moeite mogelijk om op mijn BlackBerry Dev Alpha A de data vanuit Endomondo te raadplegen en in te zien dat ik gebeld werd (hierbij was geen naam, noch een nummer zichtbaar doordat de BlackBerry Android Runtime het niet toestond om deze data raad te plegen).

Uiteindelijk bleek dit, mede door de vele disconnects, voor mij alles behalve ideaal en dus belandde deze al snel in de kast.

Hub2Watch

Lange tijd was het stil, tot ik per toeval op het artikel over Hub2Watch stuitte tijdens mijn dagelijkse bezoek aan CrackBerry.com. Ik had de Kickstarter hype rondom deze ‘Pebble’ al eerder waargenomen en het feit dat de Pebble Audio App werd getest met nummers van Spinvis was ook niet onopgemerkt aan mij voorbij gegaan. Maar de wetenschap dat ik van mijn kleuren Sony Smart Watch terug zou moeten naar een 168 pixels tellend zwart wit e-paper scherm was voor mij op dat moment echter totaal geen optie.

Het feit, dat ik een deel van de door mij nog altijd geroemde BlackBerry Flow en BlackBerry Hub experience kon extenden naar mijn pols liet mij echter niet meer los. Ik moest en zou een Pebble in mijn bezit krijgen.

Gelukkig was dit precies op het moment dat het gros van de mensen tot de ontdekking kwam ‘niet echt veel te kunnen’ met een Smart Watch en dientengevolge kon ik mijn Pebble Classic voor 50% van de prijs op de kop tikken.

Het uiterlijk van zowel het apparaat als het scherm stonden mij nog altijd tegen, maar de viertal logo’s van de laatst binnengekomen notificaties waren alles wat ik nodig had, native ondersteuning voor Pebble op BlackBerry 10 was er niet, dus ik was blij wanneer ik een keer een SMS op mijn Pebble ontving waarin stond dat mijn nieuwe factuur voor me klaar stond aangezien de WhatsApp berichten door de beperkte toegang van de Talk2Watch App niet konden worden uitgelezen. Uiteindelijk heb ik het in overleg met Rodger Leblanc, de developer van Hub2Watch wel voor elkaar gekregen dat mijn Pebble permanent de aankomende 2 agenda items ten aller tijden zichtbaar waren op mijn in CloudPebble zelf aangepaste Pebble Watchfaces, een functionaliteit die het voor mij nog altijd rechtvaardigt om mijn Smart Watch te dragen in plaats van mijn TW Steel.

De voorzichtige stapjes in Pebble C met het modificeren van Pebble Watchfaces hebben uiteindelijk ook geleid tot mijn “Passbook voor Pebble” app. Hiermee kon ik de barcode van Albert Heijn als afbeelding op mijn Pebble oproepen en zodoende een scanner bij de zelfscan terminal activeren. Technisch gezien alles behalve hoogstaand, maar functioneel erg bruikbaar.

Home Automation

Inmiddels zijn we een station verder, en wordt “Home Automatisation” steeds meer gemeen goed. Hoewel het inmiddels eigenlijk niet meer nodig is om allerlei acties ‘handmatige’ aan te sturen, kan het voor de ware control freak geen overbodige luxe zijn om de aansturing van domotica en andere zaken in en om het huis zelf in beheer te houden.

Een huishouden bestaat al gauw uit meer dan 1 persoon. Lichten in- en uitschakelen op basis van GPS is dus niet voor iedereen een vanzelfsprekendheid.

Zelf heb ik al een aantal jaren een redundant uitgevoerde oplossing in gebruik. Enerzijds bestuur ik mijn ELRO / KlikAanKlikUit via de meegeleverde ‘klikker’ en anderzijds schakelt het licht na zonsondergang automatisch mee aan tijdens het inschakelen van mijn TV ‘activiteiten’ die worden aangestuurd via mijn Logitech Harmony 1100 (en JBMedia LightManager Pro). In principe is dit voor mij meer dan toereikend. Maar soms wil je ‘even snelle’ schakelen zonder dat je ‘dieper’ de afstandsbediening in wil duiken, iets waarbij men de nodige weerstand ondervind.

Een ander bijkomend nadeel is dat ik zowel de Logitech Harmony 1100 als de JBMedia LightManager Pro voor elke nieuwe lamp, of aanpassing op de ingestelde ‘scenes’ (wanneer de lampen bijvoorbeeld later aan kunnen in de zomer ten opzichte van de winter, red.) moet ontkoppelen en via de PC software aan moet passen.

Apps zijn daarin een veel breder gemeen goed, en eenvoudig vanaf de bank aan te passen en uit te breiden, dus toen ik voor een leuk prijsje de KlikAanKlikUit Octopus Internet Control Station (ICS2000, red.) op de kop kon tikken vond ik het tijd om me dan toch maar te ‘vendor locken’ op het merk KlikAanKlikUit.

De Octopus

Hoewel Trust (het 90’s bedrijf dat vroeger niet bij iedereen hoog in het vaandel stond maar vrijwel in ieder huishouden aanwezig was, red.), het apparaat profileert als een “duizendpoot”, blijft de brede ondersteuning die wordt beloofd voor nu nog uit. Ik heb inmiddels door de jaren heen mijn ELRO schakelaars allemaal vervangen door KlikAanKlikUit schakelaars (APA3-1500R, red.) dus dit is voor mij geen tekortkoming.

De “API”

Hier kunnen we kort over zijn. Er is geen publiekelijk toegankelijke API. Op Tweakers.net had ik al gelezen dat de URL’s middels een Proxy alsnog te achterhalen zijn en met deze zoektocht heb ik mij afgelopen zaterdag dan ook kostelijk vermaakt. Met als resultaat de “API” URL’s die de KlikAanKlikUit App zelf gebruikt wanneer de gebruiker zelf niet verbonden is met het thuisnetwerk.

https://trustsmartcloud2.com/ics2000_api/command.php?action=add&command=0000&device_unique_id=0000&email=john%40doe.com&mac=0000&password_hash=0000

Een van de nadelen van de URL’s die je middels deze methode achterhaalt is dat het wachtwoord dat je voor je KlikAanKlikUit account gebruikt ‘plain’ wordt meegezonden als GET parameter in de URL.

Ik was voornemens om dit stappenplan hier uitgebreid uit de doeken te doen inclusief het opzetten van de Proxy op Windows (Fiddler, red.) en OSX (Charles, red.), totdat ik afgelopen maandag via KlikAanKlikUit op Twitter vernam dat ze hun vernieuwde oAuth API inmiddels beschikbaar hadden gesteld aan Triggi.

Wat is Triggi?

Nou hoor ik je denken, wat is Triggi? Kortweg gezegd is Triggi de Nederlandse tegenhanger van IFTTT. Je kunt ‘recepten’ opstellen waarin je een ‘als / dan’ staat definieert. Denk hierbij aan recepten waarbij je Philips Hue lampen knipperen op het moment dat jouw favoriete voetbalteam scoort of het uitschakelen van je lichten als je verder dan 1KM bij je huis vandaag bent.

Triggi Connect

Het “volledig automatiseren” is iets dat ik op dit moment niet ambieer, hoewel ik wel nadenk over interessante oplossingen. Echter kun je middels Triggi Connect ook zogeheten ‘connectoren’ aanmaken.

Deze connectoren kun je als Widget aansturen vanaf je Android Homescreen (dit kan, “beperkt” met Triggi Now, maar voor native Android Widget’s heb je momenteel nog een additionele app nodig) of roep je traditioneel van achter de browser op je computer aan.

Zelf doe ik de aansturing van de connectoren vanaf mijn Pebble met de Pebble App: HTTP Push. Via deze app kun je de connectoren (een veredelde naam voor “simpele” URL’s, red.) aanroepen waarna de ‘Trigg’ wordt uitgevoerd.

De Triggi Connect URL’s zijn geen zoekmachine vriendelijke URL’s, waardoor je deze niet zomaar uit je hoofd intypt. Ik heb zelf dus een WordPress site opgezet in mijn WordPress Network om de Triggs met eenvoudig te onthouden URL’s te kunnen triggeren. Hieroverheen heb ik met PHP een additionele “beveiligingslaag” toegevoegd zodat mijn lichten alleen worden ingeschakeld wanneer er een specifieke JSON Salt wordt meegestuurd.

Ook hier is het technische aspect absoluut van ondergeschikt belang. Maar het gebruiksgemak dat je middels deze Triggs kunt bewerkstelligen is voor mij absoluut de moeite waard.

De toekomst

Hoewel Triggi een zogeheten Cloud dienst is en je je eigen data derhalve niet volledig in beheer hebt overheerst voor mij het gemak waarmee ik Triggi kan inregelen. Met Triggi is het zelfs mogelijk om mijn Smart Home in de toekomst wellicht toch uit te breiden met het in mijn ogen “overpricedte” Philips Hue. Het begint dan ook te kriebelen om mijn ‘Smart Home’ verder uit te breiden. Een van de gedachten waar ik mee speel is het integreren van Google Home in mijn setup. Echter voel ik mij nog altijd niet comfortabel om “tegen mijn huis te praten”.

Het gebruik van Vector bestanden op jouw WordPress website

Hoewel ik me goed voor kan stellen waarom je vectoren op je website zou willen gebruiken, wil ik dit bericht graag beginnen met een kritische noot. Het toestaan van SVG in je filesystem is namelijk niet zonder risico aangezien SVG’s een nieuwe manier zijn om allerhande “injections” te faciliteren. Mocht je voldoende vertrouwen hebben in de beveiliging van je WordPress beheeromgeving en je eigen content beheren en zelfs dan nog altijd SVG’s toe willen voegen aan je site, lees dan vooral verder.

Sinds de komst van Retina schermen krijgt het gebruik van Vector bestanden gemaakt met o.a. Adobe Illustrator in plaats van Adobe Photoshop een steeds groter wordende voet aan de grond op het wereldwijde web. Vooral SVG duikt met enige regelmaat op in de vorm van iconen of andere grafische uitspattingen op websites.

SVG staat voor Scalable Vector Graphics, en dit betekend eigenlijk zoveel, als dat de afbeelding die wordt getoond, niet is opgebouwd als een bitmap uit pixels, maar, uitgeschreven vector informatie bevat. In plaats van het definiëren van de kleur van iedere pixel, zoals bij bijvoorbeeld JPG en PNG, is iedere lijn een individueel vector object. Bij de informatie van deze objecten wordt bijvoorbeeld de lengte (verhouding) en de curve opgeslagen, maar doordat dit enkel in de vorm van een scriptechnische instructie staat omschreven is de browser in staat om met logisch rekenwerk de afbeelding met behoud van scherpte te vergroten. Iets wat bij het simpelweg dupliceren van pixels niet mogelijk is.

Ben jij bang voor je eigen PHP en JS bestanden? Nee? Wat weerhoud je dan van SVG?

Hoewel je de voordelen van deze SVG bestanden prima kunt gebruiken in je Plugins en Thema's, weerhoud WordPress je er tot op heden echter nog van om SVG bestanden als eindgebruiker naar de WordPress Media Library te uploaden. En dat terwijl het op 16 augustus 2011 de W3C standaard status, “recommended” heeft verkregen.

Gebrek aan WordPress Core Ondersteuning

WordPress_SVG_ErrorUiteraard zijn we van het Core team van WordPress.org gewend dat ze het ondersteunen van een innovatief afbeeldingsformaat als SVG niet zonder reden niet aan de standaard ondersteunde extensie lijst get_allowed_mime_types() hebben toegevoegd. Zoals ook te lezen valt in trac #24251.

Een SVG is namelijk simpelweg een script in de vorm van een XML bestand zoals je dat ongeveer gewend bent van HTML, CSS, JavaScript en PHP. En dat gezegd hebbende heb je ongetwijfeld de nodige exploits voorbij zien komen, of aan den lijve mogen ondervinden bij het bezoeken van één van je favoriete websites.

Maar wanneer je geloofd in de beveiliging van jouw WordPress omgeving en de inhoud van de SVG bestanden zelf in beheer hebt. Moet je je hierdoor dan laten beperken? Volgens mij gaat het gros van de WordPress ontwikkelaars er gemakshalve ook niet van uit dat er injecties plaats vinden in de JavaScript en PHP bronbestanden, dus dan kunnen we er toch ook voor zorgen dat onze SVG niet als een ware E.T. naar “huis” gaat bellen?

“The ‘save’ way” – De Plugins

Tijdens het schrijven van dit artikel vond ik dat ik mijn mening lichtelijk moest kunnen onderbouwen alvorens ik jullie handvaten aan wilde rijken voor het ondersteunen van SVG als extensie. Tijdens deze zoektocht bleek dat het, vooral indien je zelf niet de eindgebruiker van je WordPress website bent, maar wellicht te maken hebt met klanten die wat minder technische onderbouwing hebben en daardoor de veiligheidsrisico’s van online gevonden SVG’s wellicht wat lastiger in kunnen schatten, beter werken met een WordPress plugin die een extra veiligheidscheck over de te uploaden bestanden heen laat gaan. In de WordPress Plugin Repository kom je diverse plugins tegen die de SVG’s “scannen”, “sanitizen” en “scrutinizing”. De voorbeelden die mij werden aangeraden waren: SVG Support van Benbodhi en Safe SVG van Daryll Doyle.

Proof of Concept

Uiteraard is het codevoorbeeld hieronder slechts een proof of concept waardoor ik jullie de doorontwikkeldere opties niet wilde onthouden. Onderstaand codevoorbeeld kan echter ook dienen als basis voor het ondersteunen van andere, inheemse, of maatwerk bestandsformaten zoals wij bij Dutchwebdesign ook tegenkomen voor onze klanten. Denk hierbij aan audiobestanden die over een eigen encoding beschikken of het delen van bestanden die aansluiten bij jouw core business zoals bijvoorbeeld AutoCAD bestanden.

Mocht je als ware code cowboy dus toch liever zelf aan de slag gaan, lees dan vooral verder.

“The DIY way” – Het codevoorbeeld

Er van uitgaande dat jullie de beveiliging van jullie WordPress website goed op orde hebben, kunnen we aan de slag met het toestaan van de bestandsextensie middels de upload_mimes filter in de functions.php.

/**
 * Allow uploading SVG and SVGZ file extension within the upload_mimes filter
 *
 * @author: Simon van der Steen
 * @date: 29-3-2017
 * @url: http://Simon.vdSteen.me/WordPress/gebruik-vector-bestanden-in-wordpress
 */
function svds_add_svg_mimetype( $mimes ) {
	$mimes['svg'] = 'image/svg+xml';
	$mimes['svgz'] = 'image/svg+xml';

	return $mimes;
}
add_filter( 'upload_mimes', 'svds_add_svg_mimetype', 10, 2 );

In de versies < 4.7.1 werkt het uploaden van bestanden met de *.SVG en *.SVGZ nu naar behoren, maar vanaf 4.7.1 is er een bug aangaande mimetype afhandeling (WordPress trac #39550). Om deze bug te kunnen omzeilen, dien je ook gebruik te maken van onderstaande code. Vanaf 4.7.3 zou deze workaround overigens niet meer gebruikt hoeven worden, zorg er dus voor dat je jouw WordPress installatie update.

/**
 * Suppress mimetype security measures since 4.7.1 for SVG
 *
 * @author: Simon van der Steen
 * @date: 29-3-2017
 * @url: http://Simon.vdSteen.me/WordPress/gebruik-vector-bestanden-in-wordpress
 * @source: https://wordpress.org/support/topic/wp-4-7-1-kills-svg/page/3/#post-8649196
 */
function svds_suppress_svg_security_bug( $filetype_ext_data, $file, $filename, $mimes ) {
	if ( substr($filename, -4) === '.svg' ) {
		$filetype_ext_data['ext'] = 'svg';
		$filetype_ext_data['type'] = 'image/svg+xml';
	}

	if ( substr($filename, -5) === '.svgz' ) {
		$filetype_ext_data['ext'] = 'svgz';
		$filetype_ext_data['type'] = 'image/svg+xml';
	}

	return $filetype_ext_data;
}
add_filter( 'wp_check_filetype_and_ext', 'svds_suppress_svg_security_bug', 100, 4 );

Extra voordelen van het gebruik van SVG

  • Doordat een SVG qua opbouw vrijwel gelijk is aan een XML, is het ook mogelijk om deze achteraf te stijlen. Zo kun naast het formaat oneindig uitrekken, ook één SVG gebruiken als label voor verschillende post types met een andere kleur.
  • Doordat een SVG niet is opgebouwd uit “statische” pixels en vooraf gedefinieerde afmetingen (wat voor afbeeldingen met de wat grotere afmetingen kan oplopen naar miljarden pixels (een “kleine” afbeelding van 640 x 480 bevat al 307.200 pixel, red.) en de bijkomende MB’s die het vasthouden van deze data met zich mee brengt), maar scriptregels om het lijn- en kleurwerk van de afbeelding te bepalen, scheelt dit aanzienlijk in het aantal MB’s dat een SVG in beslag neemt op je server.

Standaard Placeholder voor de Uitgelichte Afbeelding

has_post_thumbnail() hoeft niet op elk WordPress Template te worden gedefinieerd.

Steeds weer wanneer ik een nieuw template moet opzetten op basis van op maat gemaakte frontend werkzaamheden van mijn collega’s bij Dutchwebdesign zijn er een aantal standaard zaken die je keer op keer opnieuw in moet richten. Één van die zaken is de Uitgelichte afbeelding (Featured image, red.)!

Het probleem

Grafische elementen worden steeds belangrijker in websites en mede daardoor is het enkel uitsluiten van de eventueel te tonen post thumbnail op basis van de has_post_thumbnail() functionaliteit in mijn beleving niet langer toereikend. Met deze core WordPress functie kun je er inderdaad voor zorgen dat de afbeelding en eventuele omringende elementen niet worden getoond op een overzicht of pagina, maar bij de wat grafischer onderlegde designs zorgt dit ervoor dat de items zonder afbeelding in het overzicht, of als detailpagina net een stukje beleving missen of uit de toon springen.

Natuurlijk heb je de mogelijkheid om als developer een standaard afbeelding naar je thema of media library in te bouwen, welke als placeholder fungeert, maar dit is veelal een eenmalige optie waarbij jij, of je klant tot in het einde der tijden zit opgescheept met dezelfde, statische afbeelding. Én daarbij moet je voor elk overzicht, of detail template dezelfde functionaliteit toevoegen en moet degene die de doorontwikkeling op de site voor zijn of haar rekening neemt ook weten welke elementen uit bestaande templates, moeten worden hergebruikt in eventueel nieuw aan te maken templates.

De oplossing

Wanneer je besluit dat ieder bericht (van een specifiek post type) sowieso moet beschikken over een afbeelding, danwel een placeholder dan is het wellicht een beter idee om dit middels een aanpassing op de filter voor the_post_thumbnail() te doen. Op deze manier stel je de logica voor het terugvallen  op een placeholder eenmalig in en maken alle toekomstige templates en gedefinieerde afbeeldingsformaten hier gebruik van.

Bij Dutchwebdesign maken wij gebruik van een maatwerk plugin, de zogeheten Snippet Plugin. Met deze plugin zorgen wij ervoor dat klanten “Content Snippets” kunnen hergebruiken op meerdere delen van de site. Denk hierbij aan adresgegevens of het beheren van bepaalde content blokken op de homepage of in sidebars van templates etc. In onderstaand voorbeeld ga ik er gemakshalve dan ook even vanuit dat je een post, hergebruikt voor het beheerbaar maken van de  placeholder afbeelding.

Op verzoek kan ik ook de code aanleveren voor het gebruik van een statische afbeelding die is geupload naar de theme folder, via bijv. de in WordPress 4.7.0 geïntroduceerde get_theme_file_uri() functionaliteit.

Het code voorbeeld

/**
 * Post Thumbnail Placeholder filter
 *
 * @author: Simon van der Steen
 * @date: 23-3-2017
 * @url: http://Simon.vdSteen.me/WordPress/standaard-placeholder-voor-de-uitgelichte-afbeelding
 */
function svds_post_thumbnail_placeholder( $html, $post_id, $post_thumbnail_id, $size, $attr = array() ) {
	if( '' === $html ){
		//Set Snippet ID used to fetch Placeholder Image
		$intPlaceholderId = 999;

		$html = get_the_post_thumbnail( $intPlaceholderId, $size, $attr );
	}

	return $html;
}
add_filter( 'post_thumbnail_html', 'svds_post_thumbnail_placeholder', 10, 5 );

In bovenstaand voorbeeld pas je ‘999’ aan naar het WordPress post_id van de post die je gebruikt voor het beheren van de placeholder.

Wanneer je de code snippet hierboven in je functions.php plaatst, wordt met de post_thumbnail_html filter gecontroleerd of the_post_thumbnail() of get_the_post_thumbnail() inderdaad beschikt over een gerelateerde afbeelding. Indien de filter concludeert dat er inderdaad géén afbeelding is ingesteld voor de desbetreffende WordPress post, page of andersoortige post_type, dan zal het mechanisme in werking treden en de placeholder afbeelding tonen welke hoort bij het ingestelde ID.

Additionele voorbeelden

Indien gewenst zou je deze functionaliteit verder uit kunnen breiden met post type specifieke placeholders.

/**
 * Post type based Post Thumbnail Placeholder filter
 *
 * @author: Simon van der Steen
 * @date: 23-3-2017
 * @url: http://Simon.vdSteen.me/WordPress/standaard-placeholder-voor-de-uitgelichte-afbeelding
 */
function svds_post_thumbnail_placeholder( $html, $post_id, $post_thumbnail_id, $size, $attr = array() ) {
   if( '' === $html ){
      //Set Snippet ID used to fetch Placeholder Image
      $intDefaultPlaceholderId = 999;

      //Placeholders defined by ID per Post Type
      $arrPostTypePlaceholderIds = array( 'post' => 9991, 'page' => 9992 );
      
      //Check Post Type for current $post_id
      $strPostType = get_post_type( $post_id );
      
      //Check if Post Type exists within $arrPostTypePlaceholderIds
      if( array_key_exists( $strPostType, $arrPostTypePlaceholderIds ) ){
         $intPlaceholderId = $arrPostTypePlaceholderIds[$strPostType];
      }else{
         $intPlaceholderId = $intDefaultPlaceholderId;
      }

      $html = get_the_post_thumbnail( $intPlaceholderId, $size, $attr );
   }

   return $html;
}
add_filter( 'post_thumbnail_html', 'svds_post_thumbnail_placeholder', 10, 5 );

In het bovenstaande voorbeeld gebruiken we het standaard ‘berichten’ en ‘pagina’ post_type dat beschikbaar is binnen WordPress, dit is oneindig uit te breiden met custom post types.

WhatsApp Web Header

Update je WhatsApp Web Icoon

Sinds WhatsApp ons op 21 januari 2015 heeft verblijd met WhatsApp Web voor Google Chrome i.s.m. de Android, Windows Phone of BlackBerry App had ik op het eerste oog slechts 1 klein puntje van kritiek.

Default WhatsApp Web IconAangezien er momenteel nog geen WhatsApp extentie voor Google Chrome beschikbaar is moet je namelijk via “Opties -> Meer hulpprogramma’s” zelf een “Snelkoppeling maken…” om WhatsApp Web los van je browser tabs in een eigen venster te draaien. Standaard wordt hier dan de favicon.ico van de desbetreffende website voor gebruikt welke met een grootte van 16px bij 16px niet echt toereikend is.

Enhanced WhatsApp Web IconGelukkig maakt een Google Chrome snelkoppeling gebruik van de standaard snelkoppeling functionaliteit in Windows. Wanneer je met je rechtermuisknop op WhatsApp Web klikt en vervolgens voor “Eigenschappen” kiest heb je de mogelijkheid om onderin te kiezen voor “Ander pictogram…”, hier kun je eender welk *.ico bestand selecteren om als afbeelding voor deze WebApp te gebruiken. Daartoe ben ik even vlug aan de slag gaan om een scherpere variant te maken om de eerste dagen toch een wat netter icoontje in mijn startbalk te mogen aanschouwen. Hoewel het nog niet perfect is, is het zeker een verbetering t.o.v. het standaard logo.

In de komende dagen komen er wellicht nog betere varianten bij. Voor verzoekjes of vragen kun je je altijd richten tot mijn Twitter: @SimonvdSteen.

De WhatsApp Web.ico kun je hier downloaden:

Windows 7 / 3D design
Windows 8 / Flat design

WordPress Notification Update Emailaddress

Wijzig je Updatenotificatie E-mailadres

“Zelfs een lunch wordt aangegrepen voor een interessante Coding Challenge op @WordCampNL!”

Tijdens @WordCampNL ’14 ben ik in gesprek geraakt met Roel Looijen van @StudioStoneNL. Een van huis uit Designer die grafische uitspattingen in websites voor klanten realiseert met behulp van WordPress. Hij was benieuwd of het mogelijk was om de technische notificaties over WordPress updates niet langer naar het admin e-mailadres te laten versturen. Het antwoord hierop moest ik hem op dat moment helaas verschuldigd blijven, maar het zette me wel aan het denken.

Het probleem

Wanneer je in het verleden zelf een WordPress website in beheer hebt gehad, dan weet je wellicht ook dat je één administrator e-mailadres instelt dat door WordPress en vele Plugins wordt gebruikt om jou te informeren over WordPress (core-) updates, reacties en zelfs voor het versturen van contactformulieren.

Wanneer je echter, net als Roel en ondergetekende, ook websites voor andere partijen in beheer hebt, is het niet handig wanneer al het e-mailverkeer dat een website genereert op hetzelfde e-mailadres aankomt. Dit zou namelijk betekenen dat:

  • Ik, als technisch contactpersoon, update notificaties binnenkrijg, maar daarnaast ook de reacties en informatieaanvragen vanuit de contactformulieren. Met als bijkomend nadeel dat een antwoord op inhoudelijke vraagstukken langer op zich laat wachten door de extra vertragende schakel in de communicatie.
    …of…
  • Jij, als website eigenaar naast alle gerelateerde informatie over jouw website of product, ook notificaties ontvangt over (cruciale) WordPress updates die beschikbaar zijn om de veiligheid van de WordPress installatie waarop jouw website draait te optimaliseren. Iets wat tot onnodige kopzorgen kan leiden, vooral wanneer je meent actie te moeten ondernemen en eindigt met een “White Screen of Death”.

De oplossing

Met het oog op de vele ‘hooks’, ‘actions’ en ‘filters’ waar WordPress over beschikt ben ik gaan zoeken naar een mogelijkheid om de notificaties die technisch van aard zijn om te leiden naar het e-mailadres van de technische contactpersoon, welke ik uiteindelijk gevonden heb.

Het code voorbeeld

function svds_change_update_email($email){
  $email['to'] = 'John@Doe.com';
  return $email;  
}
add_filter( 'auto_core_update_email', 'svds_change_update_email');

Wanneer je de code snippet hierboven in je functions.php plaatst, wordt met de auto_core_update_email filter het e-mailadres dat gebruikt wordt voor updatenotificatie meldingen overschreven met ‘John@Doe.com’. Middels diverse filters kun je nog veel meer zaken aangaande e-mails vanuit WordPress aanpassen, zo bestaan er bijvoorbeeld wp_mail_from_name om de naam waarvan uitgaande mails vanuit jouw website worden verzonden aan te passen en wp_mail_from om het e-mailadres van waaruit e-mails worden verzonden bijvoorbeeld aan te passen naar ‘noreply@email.com’.