Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
blocks:advanced_scripting:visitor_identity_tracking [2022-05-09 17:20]
admin Clarifications
blocks:advanced_scripting:visitor_identity_tracking [2023-01-23 09:23] (current)
admin Added link toapp notes
Line 1: Line 1:
-====== Visitor Identity and Tracking ======+====== Visitor Data Collection ======
  
 A Visitor Spot in Blocks can be used as a basic entry point for visitors to connect to the system. This is essentially a URL allowing a number of visitors to all connect to the same Visitor Spot. The URL looks something like this: A Visitor Spot in Blocks can be used as a basic entry point for visitors to connect to the system. This is essentially a URL allowing a number of visitors to all connect to the same Visitor Spot. The URL looks something like this:
Line 30: Line 30:
 By selecting "Identify Individual Visitors" you gain two important abilities: By selecting "Identify Individual Visitors" you gain two important abilities:
  
-  - For //each individual visitor//independent control over child blocks, parameters, tags, custom CSS classes, etc, similar to what you have for Display Spots. +  - For //each individual visitor// you gain independent control over child blocks, parameters, tags, custom CSS classes, etc, similar to what you have for Display Spots. 
-  - The ability to collect time-stamped data on each individual visitor, such as any data being entered by that visitor, spots being visited, game scores, etc. +  - The ability to collect data on each individual visitor, such as any data being entered by that visitor, spots being visited, game scores, etc. 
  
 By combining these two abilities, you can do things such as presenting different content to a visitor depending on where she's been during her visit, points earned along the way, or any other data provided or collected during the visit. Such data can also be archived after the visit for subsequent analyzation, e.g. to understand the route taken by visitors, which exhibits they visited, how long they stayed there, etc. By combining these two abilities, you can do things such as presenting different content to a visitor depending on where she's been during her visit, points earned along the way, or any other data provided or collected during the visit. Such data can also be archived after the visit for subsequent analyzation, e.g. to understand the route taken by visitors, which exhibits they visited, how long they stayed there, etc.
Line 56: Line 56:
 === Using an Identification Token === === Using an Identification Token ===
  
-Here, a unique identification token is handed out to each visitor at the entrance. This token could for example be an RFID bracelet och tag, carried by the visitor. By scanning this token at desired stations, Blocks will learn who's where, and can collect and act on this information. The token may be returned when leaving, and recycled for new visitors.+Here, a unique identification token is handed out to each visitor at the entrance. This token could for example be an RFID bracelet och tag, carried by the visitor. By scanning this token at stations, Blocks will learn who's where, and can collect and act on this information. The token may be returned when leaving, to be recycled for new visitors.
  
 This arrangement removes the need for visitors to have and use a personal mobile phone. Depending on the information collected during the visit, this may also remove any privacy issues (assuming no personally identifiable information is collected). More on this below. This arrangement removes the need for visitors to have and use a personal mobile phone. Depending on the information collected during the visit, this may also remove any privacy issues (assuming no personally identifiable information is collected). More on this below.
Line 107: Line 107:
 ==== Data Record Declaration ==== ==== Data Record Declaration ====
  
-A key feature of this user script is to declare what data to be collected from visitors. This is done using a //record declaration//, typically located at the beginning of the script. Such a declaration could look line this:+A key feature of this user script is to declare what data to be collected from visitors. This is done using a //record declaration//, typically located at the beginning of the script. Here's an example of such record declaration:
  
 <code> <code>
Line 120: Line 120:
 </code> </code>
  
-The name of this record type is "ExampleRecord". That's the name to enter in the "Record type" field of the Identity tab in the Visitor Spot's settings. The declaration shown above has five data fields. What data fields to use and what they're called depends entirely on what data you want to collect. Each data field must be marked with the @field() decorator. +The name of this record type is "ExampleRecord". That's the name to enter in the "Record type" field of the Identity tab in the Visitor Spot's settings. The declaration shown above has five data fields. What data fields to use, their names and data types, depend entirely on what information you want to collect. Each data field must be marked with either a @field() or an @id() decorator, where @id() indicates a unique ID field (a "secondary key" in database-speak)
  
-In addition to the fields shown above, each record also has a unique identification number named //$puid//, declared in RecordBase – the base class of ExampleRecord, which all custom record declarations must extend. This $puid number can be used to uniquely identify each data record. When using the visitors mobile phone as the only identification, this matches the identity ID assigned to the phone when it first connects to Blocks through this mobile spot's URL.+In addition to the fields mentioned above, each record also has a built-in, unique identity field named //$puid//, declared in RecordBase. This is the base class of ExampleRecord, as you can see above. All custom record declarations must extend RecordBase. This $puid uniquely identifies each data record. When using a visitor'mobile phone as the only identification, this matches the identity ID assigned to the phone when it first connects to Blocks through this mobile spot's URL.
  
 === Record Field Decorators === === Record Field Decorators ===
  
-As mentioned above, each field in the record must be marked with either a @field() an @id() decorator, as shown above. In addition to these mandatory decorators, you may optionally add a @spotParameter() decorator.+As mentioned above, each field in the record must be marked with either a @field() an @id() decorator. In addition to these mandatory decorators, you may optionally add a @spotParameter() decorator.
  
-The **@id()** decorator indicates that the field is to be used as a secondary key (an "index" in database terms), allowing the record to be looked up also by this valuein addition to its $puid mentioned above. This is useful in cases where you have other means of identifying the visitor than just a mobile phone. For instance, when using an RFID tag, you'll want the ID number of the visitor's tag stored in a field marked with an @id() decorator. Note that the values in such fields //must// be unique in the system for any given record type. Thus, if you re-cycle RFID tags, you //must// delete (or archive) any previous record using that same RFID code before assigning it to an @id() field of a new visitor. More on how to delete/archive records below.+The **@id()** decorator indicates that the field is to be used as a secondary key (an "index" in database terms), allowing the record to be looked up also by this value. This index is in addition to the standard $puid field mentioned above. This is useful in cases where you have other means of identifying the visitor than just a mobile phone. For instance, when using an RFID tag, you'll want the ID number of the visitor's tag stored in a field marked with an @id() decorator. Note that the value in a @id() field //must// be unique for any given record type. Thus, if you re-cycle RFID tags, you //must// delete (or archive) any previous record using that same RFID code before assigning it to an @id() field of a new visitor. More on how to delete/archive records below. Use the @id() decorator on its own – do not combine it with @field().
  
-A **@spotParameter()** decorator causes data stored in the record to be linked to a Visitor Spot parameter with the same name. You must establish this parameter separately, making sure it has the same name and data type as the record field. This can be done either in the Block to be shown by the Visitor Spot, or on the Parameters tab of the Visitor Spot's settings. Once you've linked the record field to a spot parameter in this way, any changes made to the parameter will be reflected in the data record field and vice versa.This could, for example, be used to allow a visitor to enter a nickname on her phone, or other relevant information, then automatically stored and persisted in the visitor's data record.+A **@spotParameter()** decorator causes data stored in the record to be linked to a Visitor Spot parameter with the same name and data type. This must be used together with the @field() decorator, as shown above. You must establish this parameter separately, making sure it has the same name and data type as the record field. This must be done in the Block assigned to the Visitor Spot (here accessible as a //Local// parameter). Once you've linked the record field to a spot parameter in this way, any changes made to the parameter will be reflected in the data record field and vice versa. This could, for example, be used to allow a visitor to enter a nickname on her phone, or other relevant information, then automatically stored and persisted in the visitor's data record.
  
 +==== Creating and Finding Records ====
  
-=== Data Record Storage ===+When using a mobile phone (i.e., a Visitor Spot) as the only identifier of a visitor, the associated data record is implicitly created when the visitor connects to Blocks. A 'visitor' event is fired on the MobileSpot to indicate this. This event provides a Visitor object, which represents the individual visitor's mobile phone. The Visitor object provides access to the data record, allowing you to use this right away. 
 + 
 +When using other means of visitor identification, such as RFID, NFC or other such tokens, there's no automatic record creation. You must then listen for the ID to arrive from the token scanner. You can use a Display Spot to connect many types of such scanners, often exposing the scanned code as its //scannerInput// property- Alternatively, a Device Driver can be used to accept a code from a scanner connected to your network. Once the scanned code appears, you can either use it to look up the corresponding record (assuming it exists), using the //getRecordSec// script function. Alternatively, you can create the record using the //newRecord// Script function. Then remember to immediately store the scanner ID in an @id() field in the record, allowing you to find it later using that ID. 
 + 
 +When using a combination of identity token and mobile devices, you need to find a way by which both these methods of identification can be bound to the same record. In this case, you must use two separate @id() fields, one holding the token's ID and the other the Visitor's phone identity (available in the //identity// field of the associated Visitor object). It's often non-trivial to determine which phone belongs to which token. This can be handled, for example, using dynamically generated QR code shown on the check-in station as the ID token is handed out, where the visitor needs to scan this QR code with her phone to establish the connection. The QR code will then provide both the URL used to access Blocks and the associated token ID (as a query parameter), allowing these two to be set on the same record.  
 + 
 +=== Visitor Lifecycle === 
 + 
 +Note that the Visitor object, provided when a visitor's phone connects to Blocks, is available //only as long as the visitor's phone remains connected//. If the phone disconnects (e.g., the visitor turns it off or closes the web page), the Visitor object is discarded. This is indicated by the 'finish' event being emitted by the Visitor object. You must not hold on to or use a Visitor object beyond this point. Thus, it is important that you listen for this event and release all references to the Visitor object when this event fires. Furthermore, if you open any other event or property subscriptions associated with the Visitor object, you must close those when the Visitor goes away. Doing so avoids memory leaks and the possibility "ghost calls" into code that's no longer supposed to be alive. 
 + 
 +While the Visitor object will come and go as the visitor's phone connects and disconnects, any associated data record remains intact. hence this data record should hold all "important" data associated with a visitor. The Visitor object can be used to communicate with the individual visitor's phone, either by making explicit calls to functions available on the Visitor object or by changing the value of a record field marked with //@spotParameter()//, which will then be reflected by any Spot Parameter with the same name and type. The value of such a Spot Parameter can be used in a variety of ways on the Spot; e.g. to show information to the visitor, acting as data input, affecting property bindings, etc. 
 + 
 +==== Data Record Storage ====
  
 In addition to being available inside your user script, data records are also stored on disk inside the //record// directory located in your Blocks root directory. Inside this record directory, Blocks creates one sub-directory per record type, named by the record type ("ExampleRecord" in the example shown above). Inside such a type-specific subdirectory, you'll find one directory per record instance. This is named with //Pn// where //n// is the $puid identifier mentioned above. In addition to being available inside your user script, data records are also stored on disk inside the //record// directory located in your Blocks root directory. Inside this record directory, Blocks creates one sub-directory per record type, named by the record type ("ExampleRecord" in the example shown above). Inside such a type-specific subdirectory, you'll find one directory per record instance. This is named with //Pn// where //n// is the $puid identifier mentioned above.
Line 146: Line 159:
 You must not remove or change this file while the visitor is still active.  You must not remove or change this file while the visitor is still active. 
  
-=== Data Record Clean-up ===+==== Data Record Clean-up ====
  
 Once a visitor leaves, this data must be discarded to not consume excessive amounts of server memory as new visitors join in. Your user script must manage this clean-up of visitor data records, either one by one (as each visitor leaves or any identifying token is recycled) or en masse once closed for the day (e.g., at 3:00am every day). Once a visitor leaves, this data must be discarded to not consume excessive amounts of server memory as new visitors join in. Your user script must manage this clean-up of visitor data records, either one by one (as each visitor leaves or any identifying token is recycled) or en masse once closed for the day (e.g., at 3:00am every day).
Line 164: Line 177:
  
  
 +===== Where to go from Here =====
  
- +Here are a few [[blocks:app-note#personal_visitor_experience|application notes]] you can download and run to see how this works in practice. You can learn from these application notes, and perhaps use one of them as a starting point for building your own Personal Visitor Experience.
- +
- +
- +