dev-master
9999999-dev http://silverstripe.orgThe SilverStripe Personalisation Module
BSD-3-Clause
The Requires
by SilverStripe
by SilveStripe Super Marvellous Team
silverstripe personalisation
The SilverStripe Personalisation Module
Maintainer contacts:, (*1)
* Mark Stephens (mark@silverstripe.com) * Carlos Barberis (carlos@silverstripe.com)
This module provides personalisation services to a SilverStripe application. Personalisation schemes can be set up in the CMS, and these can be rendered into templates or other UI as desired. Each scheme typically defines variations and rules that determine which variation is presented in a given circumstance., (*2)
Variations embody presentation behaviours. Some of the built-in variations include:, (*3)
New variations can be defined by the developer., (*4)
Rules are executed within a context. This is an extendable set of properties with values that the admin user can use to define the rules. The properties are organised into a namespace. Some properties are predefined by the module, but typically a site will introduce new properties, via custom context handlers or via the tracker., (*5)
The module implements basic tracking, and can be made to use the session, a member login or a tracking cookie to track a user's actions on the site. The tracker exposes a simple API that lets the developer manipulate and query the information stored in the tracker., (*6)
The key interfaces and classes are:, (*7)
The module should be considered alpha state. Features that are current present include:, (*8)
Planned features that are not currently present include:, (*9)
You'll need SilverStripe 3.0 or higher. Put the module directory into the top-level directory of your project as usual, and perform a dev/build., (*10)
A Personalisation tab will appear in the CMS interface. By default it will enable the default tracker, which uses the SilverStripe database for storage., (*11)
The module uses the SilverStripe 3 configuration system, and provides default values for personalisation config items, which can be overridden by project as required., (*12)
DefaultContextProvider, which is the default implementer of ContextProvider, maintains a list of handlers (which themselves implement ContextProvider). There are two handlers built in, both of which are enabled:, (*13)
The default configuration is in personalisation/_config/default.yml, (*14)
To define your own context handler, you can, (*15)
Tracking is performed by the Tracker class. This maintains a list of one or more objects that implement the TrackingStore interface., (*16)
The tracker needs to be initialised before use. This is done by calling:, (*17)
Tracker::init();
This will initialise the Tracker and add DefaultTrackingStore as the sole tracking store., (*18)
Alternatively, if you want to implement your own TrackingStore, you call initialise the tracker as follows:, (*19)
Tracker::init(); Tracker::self::add_store("mytracker", "MyTrackingStoreClass");
Key information structures are: * context, which is a set of namespace property/values., (*20)
The key classes and interfaces in the module are as follows:, (*21)
The module is built to a set of principles: * Core components have interfaces, so that different components can be replaced if required. * Default implementations of these interfaces are provided and configured so there is reasonable behaviour out of the box. * Wherever possible, data and state is provisioned on-demand to minimise overhead. * The set of state that is known about the user is derived from each request., (*22)
A custom handler is a class that implements ContextProvider. It's purpose is to introduce new values into the property namespace programmatically. For example, you may have a function that maps geolocation info in the request to a regional office of a company., (*23)
The interface has two methods: * getProperties($properties) gets the values of properties that are handled by this handler. The handler only returns values for the properties it understands. * getMetadata($namespaces) returns metadata for the properties that the handler understands., (*24)
For example, lets say our project requires personalisation on regional office. We want to introduce a property called request.regional-office that we can use when we're generating variations. The value will end up being a string., (*25)
class OfficeContextHandler implements ContextProvider { static $office_property = "request.regional-office"; function getProperties($properties) { $result = array(); if (isset($properties[self::$office_property])) { $v = $this->getRegionalOfficeFromRequest(); if ($v) { $v = new ContextProperty(array( "name" => $name, "value" => $v, "confidence" => 100 // we're completely sure of the request. )); $v = array($v); // always an array, even for single values $result[$name] = $v; } } return $result; } // Return the office name, or null if we can't figure it out. We use ipinfodb.com to get lat/lng from IP, // and then find the regional office closest to this location. This assumes you have a RegionalOffice // class with Lat and Lng properties. function getRegionalOfficeFromRequest() { // http://api.ipinfodb.com/v3/ip-city/?key=<your_api_key>&ip=74.125.45.100&format=json $req = new RestfulService("http://api.ipinfodb.com/v3/ip-city/"); $req->setQueryString(array('key' => self::get_ip_info_db_key(), 'ip' => $_SERVER['REMOTE_ADDR'], 'format' => 'json')); $response = $req->request(); $data = json_decode($response->getBody()); $lng = $data->longitude; $lat = $data->latitude; $sql = "SELECT DISTINCT \"RegionalOffice\".\"ID\", (3959*acos(cos(radians($lat))*cos(radians(\"Lat\"))*cos(radians(\"Lng\")-radians($lng))+sin(radians($lat))*sin(radians(\"Lat\")))) AS distance FROM \"RegionalOffice\" ORDER BY \"distance\" ASC"; $sqlResult = DB::query($sql); $results = $sqlResult->column("ID"); if(is_array($results)) { $obj = DataObject::get_by_id("RegionalOffice", (int)$results[0]); $method = self::get_output_method(); $content = $obj->$method(); return $content; } return null; // didn't find one } function getMetadata($namespaces = null) { return array( self::$office_property => "Text" ); } }
Then, in mysite/_config.php:, (*26)
$this->register_handler(new OfficeContextHandler());
Now, whenever personalisation is invoked, and a rule references the property request.regional-office, getRegionalOfficeFromRequest() will be called and will calculate the value as required. Note that the calculation is performed on demand only., (*27)
The SilverStripe Personalisation Module
BSD-3-Clause
silverstripe personalisation