1717require_relative './params'
1818require_relative './version'
1919require_relative '../optimizely/helpers/event_tag_utils'
20+ require 'securerandom'
2021
2122module Optimizely
2223 class Event
@@ -41,198 +42,198 @@ def ==(event)
4142 end
4243
4344 class BaseEventBuilder
45+ CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'
46+
4447 attr_reader :config
45- attr_reader :params
4648
4749 def initialize ( config )
4850 @config = config
49- @params = { }
5051 end
5152
5253 private
5354
54- def add_common_params ( user_id , attributes )
55- # Add params which are used in both conversion and impression events.
56- #
57- # user_id - ID for user.
58- # attributes - Hash representing user attributes and values which need to be recorded.
59-
60- add_project_id
61- add_account_id
62- add_user_id ( user_id )
63- add_attributes ( attributes )
64- add_source
65- add_time
55+ def get_common_params ( user_id , attributes )
56+ # Get params which are used in both conversion and impression events.
57+ #
58+ # user_id - +String+ ID for user
59+ # attributes - +Hash+ representing user attributes and values which need to be recorded.
60+ #
61+ # Returns +Hash+ Common event params
62+
63+ visitor_attributes = [ ]
64+
65+ unless attributes . nil?
66+
67+ attributes . keys . each do |attribute_key |
68+ # Omit null attribute value
69+ attribute_value = attributes [ attribute_key ]
70+ next if attribute_value . nil?
71+
72+ # Skip attributes not in the datafile
73+ attribute_id = @config . get_attribute_id ( attribute_key )
74+ next unless attribute_id
75+
76+ feature = {
77+ entity_id : attribute_id ,
78+ key : attribute_key ,
79+ type : CUSTOM_ATTRIBUTE_FEATURE_TYPE ,
80+ value : attribute_value
81+ }
82+
83+ visitor_attributes . push ( feature )
84+ end
85+ end
86+
87+ common_params = {
88+ account_id : @config . account_id ,
89+ project_id : @config . project_id ,
90+ visitors : [
91+ {
92+ attributes : visitor_attributes ,
93+ snapshots : [ ] ,
94+ visitor_id : user_id
95+ }
96+ ] ,
97+ revision : @config . revision ,
98+ client_name : CLIENT_ENGINE ,
99+ client_version : VERSION
100+ }
101+
102+ common_params
66103 end
67104 end
68105
69106 class EventBuilder < BaseEventBuilder
70- CONVERSION_EVENT_ENDPOINT = 'https://logx.optimizely.com/log/event'
71- IMPRESSION_EVENT_ENDPOINT = 'https://logx.optimizely.com/log/decision'
107+ ENDPOINT = 'https://logx.optimizely.com/v1/events'
72108 POST_HEADERS = { 'Content-Type' => 'application/json' }
109+ ACTIVATE_EVENT_KEY = 'campaign_activated'
73110
74111 def create_impression_event ( experiment , variation_id , user_id , attributes )
75- # Create conversion Event to be sent to the logging endpoint.
112+ # Create impression Event to be sent to the logging endpoint.
76113 #
77- # experiment - Experiment for which impression needs to be recorded.
78- # variation_id - ID for variation which would be presented to user.
79- # user_id - ID for user.
80- # attributes - Hash representing user attributes and values which need to be recorded.
114+ # experiment - +Object+ Experiment for which impression needs to be recorded.
115+ # variation_id - +String+ ID for variation which would be presented to user.
116+ # user_id - +String+ ID for user.
117+ # attributes - + Hash+ representing user attributes and values which need to be recorded.
81118 #
82- # Returns event hash encapsulating the impression event.
119+ # Returns +Event+ encapsulating the impression event.
120+
121+ event_params = get_common_params ( user_id , attributes )
122+ impression_params = get_impression_params ( experiment , variation_id )
123+ event_params [ :visitors ] [ 0 ] [ :snapshots ] . push ( impression_params )
83124
84- @params = { }
85- add_common_params ( user_id , attributes )
86- add_decision ( experiment , variation_id )
87- add_attributes ( attributes )
88- Event . new ( :post , IMPRESSION_EVENT_ENDPOINT , @params , POST_HEADERS )
125+ Event . new ( :post , ENDPOINT , event_params , POST_HEADERS )
89126 end
90127
91128 def create_conversion_event ( event_key , user_id , attributes , event_tags , experiment_variation_map )
92129 # Create conversion Event to be sent to the logging endpoint.
93130 #
94- # event_key - Event key representing the event which needs to be recorded.
95- # user_id - ID for user.
96- # attributes - Hash representing user attributes and values which need to be recorded.
97- # event_tags - Hash representing metadata associated with the event.
98- # experiment_variation_map - Map of experiment ID to the ID of the variation that the user is bucketed into.
131+ # event_key - +String+ Event key representing the event which needs to be recorded.
132+ # user_id - +String+ ID for user.
133+ # attributes - + Hash+ representing user attributes and values which need to be recorded.
134+ # event_tags - + Hash+ representing metadata associated with the event.
135+ # experiment_variation_map - + Map+ of experiment ID to the ID of the variation that the user is bucketed into.
99136 #
100- # Returns event hash encapsulating the conversion event.
101-
102- @params = { }
103- add_common_params ( user_id , attributes )
104- add_conversion_event ( event_key )
105- add_event_tags ( event_tags )
106- add_layer_states ( experiment_variation_map )
107- Event . new ( :post , CONVERSION_EVENT_ENDPOINT , @params , POST_HEADERS )
108- end
109-
110- private
137+ # Returns +Event+ encapsulating the conversion event.
111138
112- def add_common_params ( user_id , attributes )
113- super
114- @params [ 'isGlobalHoldback' ] = false
139+ event_params = get_common_params ( user_id , attributes )
140+ conversion_params = get_conversion_params ( event_key , event_tags , experiment_variation_map )
141+ event_params [ :visitors ] [ 0 ] [ :snapshots ] = conversion_params ;
142+
143+ Event . new ( :post , ENDPOINT , event_params , POST_HEADERS )
115144 end
116145
117- def add_project_id
118- @params [ 'projectId' ] = @config . project_id
119- end
120-
121- def add_account_id
122- @params [ 'accountId' ] = @config . account_id
123- end
124-
125- def add_user_id ( user_id )
126- @params [ 'visitorId' ] = user_id
127- end
128-
129- def add_attributes ( attributes )
130- @params [ 'userFeatures' ] = [ ]
131-
132- return if attributes . nil?
133-
134- attributes . keys . each do |attribute_key |
135- # Omit falsy or nil attribute values
136- attribute_value = attributes [ attribute_key ]
137- next unless attribute_value
138-
139- # Skip attributes not in the datafile
140- attribute_id = @config . get_attribute_id ( attribute_key )
141- next unless attribute_id
146+ private
142147
143- feature = {
144- 'id' => attribute_id ,
145- 'name' => attribute_key ,
146- 'type' => 'custom' ,
147- 'value' => attribute_value ,
148- 'shouldIndex' => true ,
149- }
150- @params [ 'userFeatures' ] . push ( feature )
151- end
152- end
148+ def get_impression_params ( experiment , variation_id )
149+ # Creates object of params specific to impression events
150+ #
151+ # experiment - +Hash+ experiment for which impression needs to be recorded
152+ # variation_id - +string+ ID for variation which would be presented to user
153+ #
154+ # Returns +Hash+ Impression event params
153155
154- def add_decision ( experiment , variation_id )
155156 experiment_key = experiment [ 'key' ]
156157 experiment_id = experiment [ 'id' ]
157- @params [ 'layerId' ] = @config . experiment_key_map [ experiment_key ] [ 'layerId' ]
158- @params [ 'decision' ] = {
159- 'variationId' => variation_id ,
160- 'experimentId' => experiment_id ,
161- 'isLayerHoldback' => false ,
158+
159+ impressionEventParams = {
160+ decisions : [ {
161+ campaign_id : @config . experiment_key_map [ experiment_key ] [ 'layerId' ] ,
162+ experiment_id : experiment_id ,
163+ variation_id : variation_id ,
164+ } ] ,
165+ events : [ {
166+ entity_id : @config . experiment_key_map [ experiment_key ] [ 'layerId' ] ,
167+ timestamp : get_timestamp ( ) ,
168+ key : ACTIVATE_EVENT_KEY ,
169+ uuid : get_uuid ( )
170+ } ]
162171 }
172+
173+ impressionEventParams ;
163174 end
164175
165- def add_event_tags ( event_tags )
166- @params [ 'eventFeatures' ] ||= [ ]
167- @params [ 'eventMetrics' ] ||= [ ]
176+ def get_conversion_params ( event_key , event_tags , experiment_variation_map )
177+ # Creates object of params specific to conversion events
178+ #
179+ # event_key - +String+ Key representing the event which needs to be recorded
180+ # event_tags - +Hash+ Values associated with the event.
181+ # experiment_variation_map - +Hash+ Map of experiment IDs to bucketed variation IDs
182+ #
183+ # Returns +Hash+ Impression event params
168184
169- return if event_tags . nil?
185+ conversionEventParams = [ ]
170186
171- event_tags . each_pair do |event_tag_key , event_tag_value |
172- next if event_tag_value . nil?
187+ experiment_variation_map . each do |experiment_id , variation_id |
173188
174- event_feature = {
175- 'name' => event_tag_key ,
176- 'type' => 'custom' ,
177- 'value' => event_tag_value ,
178- 'shouldIndex' => false ,
189+ single_snapshot = {
190+ decisions : [ {
191+ campaign_id : @config . experiment_id_map [ experiment_id ] [ 'layerId' ] ,
192+ experiment_id : experiment_id ,
193+ variation_id : variation_id ,
194+ } ] ,
195+ events : [ ] ,
179196 }
180- @params [ 'eventFeatures' ] . push ( event_feature )
181197
182- end
183-
184- event_value = Helpers ::EventTagUtils . get_revenue_value ( event_tags )
185-
186- if event_value
187- event_metric = {
188- 'name' => 'revenue' ,
189- 'value' => event_value
198+ event_object = {
199+ entity_id : @config . event_key_map [ event_key ] [ 'id' ] ,
200+ timestamp : get_timestamp ( ) ,
201+ uuid : get_uuid ( ) ,
202+ key : event_key ,
190203 }
191- @params [ 'eventMetrics' ] . push ( event_metric )
192- end
193204
194- end
205+ if event_tags
206+ revenue_value = Helpers ::EventTagUtils . get_revenue_value ( event_tags )
207+ if revenue_value
208+ event_object [ :revenue ] = revenue_value
209+ end
195210
196- def add_conversion_event ( event_key )
197- # Add conversion event information to the event.
198- #
199- # event_key - Event key representing the event which needs to be recorded.
211+ numeric_value = Helpers :: EventTagUtils . get_numeric_value ( event_tags )
212+ if numeric_value
213+ event_object [ :value ] = numeric_value
214+ end
200215
201- event_id = @config . event_key_map [ event_key ] [ 'id' ]
202- event_name = @config . event_key_map [ event_key ] [ 'key' ]
216+ event_object [ :tags ] = event_tags
217+ end
203218
204- @params [ 'eventEntityId' ] = event_id
205- @params [ 'eventName' ] = event_name
206- end
219+ single_snapshot [ :events ] = [ event_object ]
207220
208- def add_layer_states ( experiments_map )
209- # Add layer states information to the event.
210- #
211- # experiments_map - Hash with experiment ID as a key and variation ID as a value.
212-
213- @params [ 'layerStates' ] = [ ]
214-
215- experiments_map . each do |experiment_id , variation_id |
216- layer_state = {
217- 'layerId' => @config . experiment_id_map [ experiment_id ] [ 'layerId' ] ,
218- 'decision' => {
219- 'variationId' => variation_id ,
220- 'experimentId' => experiment_id ,
221- 'isLayerHoldback' => false ,
222- } ,
223- 'actionTriggered' => true ,
224- }
225- @params [ 'layerStates' ] . push ( layer_state )
221+ conversionEventParams . push ( single_snapshot )
226222 end
223+
224+ conversionEventParams
227225 end
228226
229- def add_source
230- @params [ 'clientEngine' ] = 'ruby-sdk'
231- @params [ 'clientVersion' ] = VERSION
227+ def get_timestamp
228+ # Returns +Integer+ Current timestamp
229+
230+ ( Time . now . to_f * 1000 ) . to_i
232231 end
233232
234- def add_time
235- @params [ 'timestamp' ] = ( Time . now . to_f * 1000 ) . to_i
233+ def get_uuid
234+ # Returns +String+ Random UUID
235+
236+ SecureRandom . uuid
236237 end
237238 end
238239end
0 commit comments