Ad van der Kolk


Ad van der Kolk

A/B en MV testen (vervolg)

We gaan wat dieper in op de manier waarop je A/B MV tests kunt implementeren.
De eerste stap is het uitbreiden van de contenttype(n) die je wilt testen, met een aantal velden. Een voorbeeld zie je in de afbeelding.

In een apart tabblad zijn drie velden opgenomen. Het eerste veld koppelt de layout varianten die je wilt testen met het testitem. Het tweede veld is een lijst van targets die op het testitem aanwezig zijn. Dit zijn de items die kunnen leiden tot een conversie. Als laatste een slider waarmee je aangeeft in hoeverre de standaard layout meetelt bij het genereren van de random layout. Als de standaard testpagina bijvoorbeeld nu al geld oplevert, dan wil je het risico dat je geld misloopt omdat de standaardpagina veel minder getoond wordt, beperken. Dat doe je door het gewicht van standaardpagina in te stellen. Hiermee wordt een gewogen random keuze gemaakt uit de gekoppelde layouts.

De tweede stap is het aanpassen van de translatie die de layout van het item opvraagt. In deze translatie voeg je code toe die (gewogen) random, een layout uit de gekoppelde layouts selecteert. Hieronder staat wat voorbeeld code.
De 'gewogen' randomizer werkt als volgt:

  • genereer een getal tussen 1 en 100
  • als het getal kleiner of gelijk is dan het ingegeven gewicht, kies dan de standaardlayout
  • als het groter is dan het gewicht, kies dan random uit het interval [gewicht,100]

Smartsite SXML CopyCode image Copy Code
<se:sqlquery save="dtlayout" rem="get assigned AB Testing layouts from contentrelation ABLAYOUTS">
  <se:parameters>
   <se:parameter name="resulttype">datatable</se:parameter>
   <se:parameter name="sql">
    SELECT TOP 10 c.Nr FROM ContentRelations cr
    INNER JOIN vwActive c ON cr.nrTo = c.Nr
    INNER JOIN ContentRelationTypes crt ON cr.nrType = crt.Nr
    WHERE crt.Code = 'ABLAYOUTS' AND cr.nrFrom=?:nr
   </se:parameter>
   <se:parameter name="params">
     <se:collection>
       <se:member name="nr" type="integer">{itemdata.number()}</se:member>
     </se:collection>
   </se:parameter>
 </se:parameters>
</se:sqlquery>
{datatable.rows.insertat(dtlayout,1,$layout)}
{buffer.set(N,datatable.rows.count(dtlayout))}
{buffer.set(layout,Page,(sys.iif( $N == 0,data_navigate(layout, nr, default=$layout, 
             error=$layout),datatable.getvalue(dtlayout,ab_weighted_randomizer($ControlWeight,$N),1))))}

Om te registreren welke layout actueel is, kun je een sessie cookie gebruiken. Hierin leg je vast welke layout is gegenereerd. Daarnaast registreer je de layout in SMI met de viper: smi.store(). In de voorbeeldcode hieronder wordt de layout naam met extra informatie (in dit geval de description van het layout item) vastgelegd in zowel het cookie als in SMI.

Smartsite SXML CopyCode image Copy Code
<se:if expression="smi.isinstalled()"> 
   {buffer.set(layoutname,Page, itemdata.field(title,buffer.get(layout,Page)) +'-'+itemdata.field(description,buffer.get(layout,Page)))}
   {response.setcookie($GL_sessionid,buffer.get(layoutname,Page))} 
   {smi.store('ABTest_Cat','layoutnr_AB',buffer.get(layout,Page),itemdata.number())}
   {smi.store('ABTest_Cat','layoutname_AB',buffer.get(layoutname,Page),itemdata.number())}
</se:if>

Als laatste moeten we de conversie registreren. De conversie is dit geval het klikken door de bezoeker op de banner. Hiermee wordt de bezoeker naar een ander item gestuurd. Deze gebeurtenis kunnen we registreren door het doelitem (target), uit te rusten met wat registratie code. Deze code moet achterhalen vanuit welke layout het doelitem is aangeroepen en vervolgens deze informatie in SMI registreren. Voorbeeld code hieronder.
In de code wordt rekening gehouden met de mogelijkheid dat een aanroep van het item niet via het testitem gaat.

Smartsite SXML CopyCode image Copy Code
{buffer.set(sessionid,translation.arg(session))}
{buffer.set(prefix1,ab_prefix_variant())}
{buffer.set(prefix2,ab_prefix_non_variant())}
<!--// 
       Get layout variant. If the request came from a AB Test variant layout then 
       register this event in SMI as such. Else register this event as originated 
       by a None-variant layout
-->
{buffer.set(cookie,request.getcookie($sessionid))}
<se:if expression="$cookie != 'no_variant' AND $cookie !='' ">
 <se:then>
   {buffer.set(smi_value,request.getcookie($sessionid))}
   <!--// Store value in SMI -->
   {buffer.set(SMI_category,$prefix1+itemdata.name())}
   {smi.store('MVTest',$SMI_category,$smi_value)}
 </se:then>
 <se:else>
   {buffer.set(smi_value,'None_layout_variant_from: '+ request.referrer())}
   {buffer.set(SMI_category,$prefix2+itemdata.name())}
   {smi.store('MVTest',$SMI_category,$smi_value)}
 </se:else>
</se:if>
{response.setcookie($sessionid,'no_variant')}

In SMI kun je nu de resultaten zien.



Om het geheel af te ronden, kun je de gegevens presenteren in een tabel, waarbij je dynamisch de data uit SMI haalt.
In zo'n tabel kun je een overzicht geven van de conversierates die behaald zijn.

Hieronder staan de resultaten van een MV test van een webpagina. Op deze pagina bevindt zich een banner. De banner wordt op de pagina via drie varianten gepositioneerd:

  • Standaard variant, banner in de middenkolom;
  • Variant A, banner in de rechterkolom;
  • Variant B, banner in de linkerkolom.
Standaard Variant A variant B

De varianten worden met een gewogen random getal gekozen. De standaard variant kan een hoger of lager gewicht toegekend worden, afhankelijk van het risico dat je wilt nemen met het aanpassen van de standaard webpagina. Hoe hoger het gewicht, hoe vaker de bezoeker de standaard variant ziet. De alternatieve varianten A en B worden met gelijk gewicht random gekozen.
de conversierate is als volgt gedefinieerd.

                                   Banner Clicks
Conversierate =   ------------------------
                                 Bezoekers Pagina

 

 

Posted by Ad van der Kolk on Friday, August 05, 2011 11:07:44 PM
You are not allowed to post here.
All Blogs
Johan Blok
Features, projects, ambitions
Ad van der Kolk
About van alles en nog wat
Vincent Baaij
Showing it, Making sites with it, Adapting it, Refining it, Telling about it, Selling it, Investigating it, Teaching it and Expanding it.
Johan den Ouden
Smartsite storyteller
Demian Buijs
The art of Smartsite iXperion
Marc Derksen
What is happening at Smartsite R&D.
Marc van Neerven
Marc's shared thoughts...
Twan Meijerink
About new projects, quality assurance and me ;-)
Douwe de Wilde
About security, maybe more...
Mike Perquin
About WCF, Outscaling, database maintenance (SQL server), etc.
René Pronk
while (true);
Erwin Rijss
About building sites and more...
Recent Blog Comments
Marc van Neerven
17 April 2012, 13:30
An issue has been reported that expanding of hyperlinks fails when immediately followed by '.' or ','....
Ruben Verschueren
30 January 2012, 15:31
I get an 'operation has timed out' error (even for the examples). however if I browse to the uri's...
Marc van Neerven
12 August 2011, 16:50
Added a new (Web-guidelines compliant) download.
Marc van Neerven
12 August 2011, 14:33
Just added an update (3.0) which produces compliant XHTML and has been adapted for strict Web Guidelines...
Johan den Ouden
10 August 2011, 10:38
Uiteraard is bovenstaande code ook in een virtual assembly te gieten zodat een dll niet meer noodzakelijk...

Profile
Latest additions
Smartsite iXperion 1.4 build 6 has been released! locked
Twan Meijerink, 01 May 2012, 14:42
Workbench beta has expired
Hank Brandwijk, 11 January 2012, 16:53
Smartsite iXperion 1.4 build 4 has been released! locked
Twan Meijerink, 02 December 2011, 11:04
The second life of XForms
Marc van Neerven, 04 November 2011, 18:34
How to hide a property in a custom module? locked
Peter van der Waal, 17 October 2011, 09:31
Microsoft Certified Partner Logo