UBI client data structures

Data structures are used to create events that follow the User Behavior Insights (UBI) event schema specification. For more information about the schema, see UBI index schemas.

You must provide an implementation for the following functions:

  • getClientId()
  • getQueryId()

You can also optionally provide an implementation for the following functions:

  • getSessionId()
  • getPageId()

The following JavaScript structures can be used as a starter implementation to serialize UBI events into schema-compatible JSON:

  1. /*********************************************************************************************
  2. * Ubi Event data structures
  3. * The following structures help ensure adherence to the UBI event schema
  4. *********************************************************************************************/
  5. export class UbiEventData {
  6. constructor(object_type, id=null, description=null, details=null) {
  7. this.object_id_field = object_type;
  8. this.object_id = id;
  9. this.description = description;
  10. this.object_detail = details;
  11. }
  12. }
  13. export class UbiPosition{
  14. constructor({ordinal=null, x=null, y=null, trail=null}={}) {
  15. this.ordinal = ordinal;
  16. this.x = x;
  17. this.y = y;
  18. if(trail)
  19. this.trail = trail;
  20. else {
  21. const trail = getTrail();
  22. if(trail && trail.length > 0)
  23. this.trail = trail;
  24. }
  25. }
  26. }
  27. export class UbiEventAttributes {
  28. /**
  29. * Tries to prepopulate common event attributes
  30. * The developer can add an `object` that the user interacted with and
  31. * the site `position` information relevant to the event
  32. *
  33. * Attributes, other than `object` or `position` can be added in the form:
  34. * attributes['item1'] = 1
  35. * attributes['item2'] = '2'
  36. *
  37. * @param {*} attributes: object with general event attributes
  38. * @param {*} object: the data object the user interacted with
  39. * @param {*} position: the site position information
  40. */
  41. constructor({attributes={}, object=null, position=null}={}) {
  42. if(attributes != null){
  43. Object.assign(this, attributes);
  44. }
  45. if(object != null && Object.keys(object).length > 0){
  46. this.object = object;
  47. }
  48. if(position != null && Object.keys(position).length > 0){
  49. this.position = position;
  50. }
  51. this.setDefaultValues();
  52. }
  53. setDefaultValues(){
  54. try{
  55. if(!this.hasOwnProperty('dwell_time') && typeof TimeMe !== 'undefined'){
  56. this.dwell_time = TimeMe.getTimeOnPageInSeconds(window.location.pathname);
  57. }
  58. if(!this.hasOwnProperty('browser')){
  59. this.browser = window.navigator.userAgent;
  60. }
  61. if(!this.hasOwnProperty('page_id')){
  62. this.page_id = window.location.pathname;
  63. }
  64. if(!this.hasOwnProperty('session_id')){
  65. this.session_id = getSessionId();
  66. }
  67. if(!this.hasOwnProperty('page_id')){
  68. this.page_id = getPageId();
  69. }
  70. if(!this.hasOwnProperty('position') || this.position == null){
  71. const trail = getTrail();
  72. if(trail.length > 0){
  73. this.position = new UbiPosition({trail:trail});
  74. }
  75. }
  76. // ToDo: set IP
  77. }
  78. catch(error){
  79. console.log(error);
  80. }
  81. }
  82. }
  83. export class UbiEvent {
  84. constructor(action_name, {message_type='INFO', message=null, event_attributes={}, data_object={}}={}) {
  85. this.action_name = action_name;
  86. this.client_id = getClientId();
  87. this.query_id = getQueryId();
  88. this.timestamp = Date.now();
  89. this.message_type = message_type;
  90. if( message )
  91. this.message = message;
  92. this.event_attributes = new UbiEventAttributes({attributes:event_attributes, object:data_object});
  93. }
  94. /**
  95. * Use to suppress null objects in the json output
  96. * @param key
  97. * @param value
  98. * @returns
  99. */
  100. static replacer(key, value){
  101. if(value == null ||
  102. (value.constructor == Object && Object.keys(value).length === 0)) {
  103. return undefined;
  104. }
  105. return value;
  106. }
  107. /**
  108. *
  109. * @returns json string
  110. */
  111. toJson() {
  112. return JSON.stringify(this, UbiEvent.replacer);
  113. }
  114. }

copy

Sample usage

  1. export function logUbiMessage(event_type, message_type, message){
  2. let e = new UbiEvent(event_type, {
  3. message_type:message_type,
  4. message:message
  5. });
  6. logEvent(e);
  7. }
  8. export function logDwellTime(action_name, page, seconds){
  9. console.log(`${page} => ${seconds}`);
  10. let e = new UbiEvent(action_name, {
  11. message:`On page ${page} for ${seconds} seconds`,
  12. event_attributes:{
  13. session_id: getSessionId()},
  14. dwell_seconds:seconds
  15. },
  16. data_object:TimeMe
  17. });
  18. logEvent(e);
  19. }
  20. /**
  21. * ordinal is the number within a list of results
  22. * for the item that was clicked
  23. */
  24. export function logItemClick(item, ordinal){
  25. let e = new UbiEvent('item_click', {
  26. message:`Item ${item['object_id']} was clicked`,
  27. event_attributes:{session_id: getSessionId()},
  28. data_object:item,
  29. });
  30. e.event_attributes.position.ordinal = ordinal;
  31. logEvent(e);
  32. }
  33. export function logEvent( event ){
  34. // some configured http client
  35. return client.index( index = 'ubi_events', body = event.toJson());
  36. }

copy