17
17
require_relative './params'
18
18
require_relative './version'
19
19
require_relative '../optimizely/helpers/event_tag_utils'
20
+ require 'securerandom'
20
21
21
22
module Optimizely
22
23
class Event
@@ -41,198 +42,198 @@ def ==(event)
41
42
end
42
43
43
44
class BaseEventBuilder
45
+ CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'
46
+
44
47
attr_reader :config
45
- attr_reader :params
46
48
47
49
def initialize ( config )
48
50
@config = config
49
- @params = { }
50
51
end
51
52
52
53
private
53
54
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
66
103
end
67
104
end
68
105
69
106
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'
72
108
POST_HEADERS = { 'Content-Type' => 'application/json' }
109
+ ACTIVATE_EVENT_KEY = 'campaign_activated'
73
110
74
111
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.
76
113
#
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.
81
118
#
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 )
83
124
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 )
89
126
end
90
127
91
128
def create_conversion_event ( event_key , user_id , attributes , event_tags , experiment_variation_map )
92
129
# Create conversion Event to be sent to the logging endpoint.
93
130
#
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.
99
136
#
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.
111
138
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 )
115
144
end
116
145
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
142
147
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
153
155
154
- def add_decision ( experiment , variation_id )
155
156
experiment_key = experiment [ 'key' ]
156
157
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
+ } ]
162
171
}
172
+
173
+ impressionEventParams ;
163
174
end
164
175
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
168
184
169
- return if event_tags . nil?
185
+ conversionEventParams = [ ]
170
186
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 |
173
188
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 : [ ] ,
179
196
}
180
- @params [ 'eventFeatures' ] . push ( event_feature )
181
197
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 ,
190
203
}
191
- @params [ 'eventMetrics' ] . push ( event_metric )
192
- end
193
204
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
195
210
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
200
215
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
203
218
204
- @params [ 'eventEntityId' ] = event_id
205
- @params [ 'eventName' ] = event_name
206
- end
219
+ single_snapshot [ :events ] = [ event_object ]
207
220
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 )
226
222
end
223
+
224
+ conversionEventParams
227
225
end
228
226
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
232
231
end
233
232
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
236
237
end
237
238
end
238
239
end
0 commit comments