CakePHP Google Keyword highlighting

Gebruikers zien op 90 procent van de sites (na het klikken op een relevant zoekresultaat in Google) niet in één oogopslag waar hun zoekwoorden te vinden zijn. Voor CakePHP applicaties is het vanaf nu een fluitje van een cent om deze functionaliteit toe te voegen.

Als een bezoeker je site bezoekt, wil hij zo snel mogelijk een antwoord op de volgende vraag: is dit wat ik zoek? Als de bezoeker het antwoord op deze vraag niet snel genoeg kan vinden, gaat hij weg met een negatieve ervaring, ook al was de pagina heel relevant. Dit is vervelend voor zowel de bezoeker als voor de eigenaar van een website: voor de bezoeker was het verloren tijd, voor de eigenaar van de website een misgelopen kans op een (nieuwe) klant.

De oplossing voor het probleem is relatief simpel te noemen: laat op de pagina waar je bezoeker binnenkomt, direct de zoekwoorden van de bezoeker highlighten. Zo kan de bezoeker zelf inschatten of deze pagina relevant is voor hem. Een functionaliteit als deze is eigenlijk zeer makkelijk te maken, is goed voor de gebruikerservaring, en toch doet niemand het. Waarom? Ik zou het eigenlijk niet weten, en voor CakePHP'ers is er nu helemaal geen excuus meer: ik heb het werk al gedaan.

Hoe werkt het precies?

  1. In het beforeFilter van de AppController wordt bekeken of de referrer Google was;
  2. Zoja, dan worden de keywords waarop gezocht is in een variabele ($keywords_for_layout) gezet.
  3. In de layout worden de keywords door middel van jQuery op een mooie manier gepresenteerd, en kan de highlighting weer simpel worden verwijderd.

Installatie en gebruik

Allereerst gaan we een functie toevoegen aan AppController: setKeywords. Deze functie zorgt ervoor dat de variabele keywords_for_layout wordt gevult, indien nodig (Als het bestand app_controller.php niet bestaat in je app map, dan moet je hem eerst aanmaken). De code:


/**
 * Checks referrer and if referrer is Google; make keywords available in layout.
 *
 * @return void
 * @see http://lists.evolt.org/archive/Week-of-Mon-20040202/154831.html
 * @author Bjorn Post
 */
function setKeywords()
{
    if(!empty($_SERVER["HTTP_REFERER"]))
    {
        $referrer = $_SERVER["HTTP_REFERER"];
    }
                    
    if(isset($referrer))
    {
        if(strpos($referrer, "google"))
        {
            $a = substr($referrer, strpos($referrer, "q="));        
            $a = substr($a, 2);
            if(strpos($a, "&"))
            {
                $a = substr($a, 0,strpos($a,"&"));
            }
            $this->set('keywords_for_layout', urldecode($a));
        }
    }
}

Om ervoor te zorgen dat de code bij iedere action wordt uitgevoerd, gaan we de functie aanroepen vanuit het beforeFilter in de AppController:


function beforeFilter() {
    $this->setKeywords();
}

Om de highlighting makkelijk toe te passen in een view, heb ik een Helper geschreven. Deze kun je in je AppController toevoegen aan de array met helpers. De helper heet Highlight. De code van de helper dien je op te slaan in app/views/helpers/highlight.php. De Helper zorgt ervoor dat we gemakkelijk jQuery kunnen laden op het moment dat dat nodig is, en dat er een standaard popupje beschikbaar is in de view. Uiteraard kun je ervoor kiezen om de helper niet te gebruiken, en de code naar je layout te copy-pasten.


<?php
Class HighlightHelper extends AppHelper {
  /**
   * Returns a standard popup
   *
   * @return string div element with a default popup.
   * @author Bjorn Post
   */
  function popup()
  {
    return '<div id="highlight-popup" style="display:none"><p>Howdy stranger, since you visited this using Google, we\'ve highlighted your search keywords. <a href="#" id="remove-highlight">Remove highlighting.</a></p></div>';  
  }
  
  /**
   * Easy including of the required javascripts.
   *
   * @return void
   * @author Bjorn Post
   * @see http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
   */
  function javascript($keywords = null)
  {
    App::import('Helper', 'Javascript');
    $javascript = new JavascriptHelper();
  
    $script = $javascript->link(array('http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.js', 'highlight'));
    $script .= '<script type="text/javascript">
    $(document).ready(function() {
      var words = "'. $keywords . '";
      $.each(words.split(" "), function(idx, val) { $("#content").highlight(val); });
      $("#highlight-popup").fadeIn(600);      
 
      $("a#remove-highlight").click(function(){
        $("#content").removeHighlight();
        $("#highlight-popup").fadeOut(300);
        return false;
      });
    });</script>';
  
    return $script;
  }
}
?>

Als een-na-laatste stap, moeten we de Helper nog aanroepen. Dit doen we in de layout, het beste net voor de </body> tag:


<?php
// add this piece of code just before the 
if(isset($keywords_for_layout))
{
  echo $highlight->javascript($keywords_for_layout);
  echo $highlight->popup();
}
?>

De laatste stap is het toevoegen van wat opmaak aan het geheel:


/* keyword highlight */
.highlight {
    background: #ffefaf;
    color: #222;
    padding: .1em;
}

#highlight-popup {
    text-align: center;
    background: #ffefaf;
    color: #222;
    padding: .5em 1em;
    position: fixed;
    top: 0;
    font-size: .8em;
    width: 100%;
    border-bottom: 1px solid #f3c800;
}

#highlight-popup a {
    color: #222;
    font-weight: bold;
}

Als alles goed is gegaan, werkt het nu prima! Ik raad je aan om tijdens het testen een extra if-je in je code te zetten, zodat de variabele keywords_for_layout altijd iets bevat; dat maakt het werken wel zo gemakkelijk. Alle code is terug te vinden (en makkelijk te downloaden) in mijn GitHub repository.

Have fun!


Reacties

Er zijn op dit moment geen reacties.