vwo-sdk 1.5.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -89,7 +89,7 @@ class VWO
89
89
  # @param [String] :custom_variables_value Value from the custom_variables
90
90
  #
91
91
  # @return [Boolean]
92
- def evaluate_operand?(operand, custom_variables)
92
+ def evaluate_custom_variable?(operand, custom_variables)
93
93
  # Extract custom_variable_key and custom_variables_value from operand
94
94
 
95
95
  operand_key, operand = get_key_value(operand)
@@ -109,6 +109,14 @@ class VWO
109
109
  # Call the self method corresponding to operand_type to evaluate the result
110
110
  public_send("#{operand_type}?", operand_value, custom_variables_value)
111
111
  end
112
+
113
+ def evaluate_user?(operand, custom_variables)
114
+ users = operand.split(',')
115
+ users.each do |user|
116
+ return true if user.strip == custom_variables['_vwo_user_id']
117
+ end
118
+ false
119
+ end
112
120
  end
113
121
  end
114
122
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -50,7 +50,9 @@ class VWO
50
50
  elsif operator == OperatorTypes::OR
51
51
  sub_dsl.any? { |y| evaluate_util(y, custom_variables) }
52
52
  elsif operator == OperandTypes::CUSTOM_VARIABLE
53
- @operand_evaluator.evaluate_operand?(sub_dsl, custom_variables)
53
+ @operand_evaluator.evaluate_custom_variable?(sub_dsl, custom_variables)
54
+ elsif operator == OperandTypes::USER
55
+ @operand_evaluator.evaluate_user?(sub_dsl, custom_variables)
54
56
  end
55
57
  end
56
58
 
@@ -66,35 +68,12 @@ class VWO
66
68
  #
67
69
  def evaluate(campaign_key, user_id, dsl, custom_variables)
68
70
  result = evaluate_util(dsl, custom_variables) if valid_value?(dsl)
69
- if result
70
- @logger.log(
71
- LogLevelEnum::INFO,
72
- format(
73
- LogMessageEnum::InfoMessages::USER_PASSED_PRE_SEGMENTATION,
74
- file: FileNameEnum::SegmentEvaluator,
75
- user_id: user_id,
76
- campaign_key: campaign_key,
77
- custom_variables: custom_variables
78
- )
79
- )
80
- else
81
- @logger.log(
82
- LogLevelEnum::INFO,
83
- format(
84
- LogMessageEnum::InfoMessages::USER_FAILED_PRE_SEGMENTATION,
85
- file: FileNameEnum::SegmentEvaluator,
86
- user_id: user_id,
87
- campaign_key: campaign_key,
88
- custom_variables: custom_variables
89
- )
90
- )
91
- end
92
71
  result
93
72
  rescue StandardError => e
94
73
  @logger.log(
95
74
  LogLevelEnum::ERROR,
96
75
  format(
97
- LogMessageEnum::ErrorMessages::PRE_SEGMENTATION_ERROR,
76
+ LogMessageEnum::ErrorMessages::SEGMENTATION_ERROR,
98
77
  file: FileNameEnum::SegmentEvaluator,
99
78
  user_id: user_id,
100
79
  campaign_key: campaign_key,
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -25,7 +25,6 @@ class VWO
25
25
 
26
26
  PROTOCOL = 'https'
27
27
  HOSTNAME = ::VWO::CONSTANTS::ENDPOINTS::BASE_URL
28
- PATH = ::VWO::CONSTANTS::ENDPOINTS::ACCOUNT_SETTINGS
29
28
 
30
29
  def initialize(account_id, sdk_key)
31
30
  @account_id = account_id
@@ -40,7 +39,7 @@ class VWO
40
39
  # as received from the server,
41
40
  # nil if no settings_file is found or sdk_key is incorrect
42
41
 
43
- def get_settings_file
42
+ def get_settings_file(is_via_webhook = false)
44
43
  is_valid_key = valid_number?(@account_id) || valid_string?(@account_id)
45
44
 
46
45
  unless is_valid_key && valid_string?(@sdk_key)
@@ -48,7 +47,12 @@ class VWO
48
47
  return '{}'
49
48
  end
50
49
 
51
- vwo_server_url = "#{PROTOCOL}://#{HOSTNAME}#{PATH}"
50
+ if is_via_webhook
51
+ path = ::VWO::CONSTANTS::ENDPOINTS::WEBHOOK_SETTINGS_URL
52
+ else
53
+ path = ::VWO::CONSTANTS::ENDPOINTS::SETTINGS_URL
54
+ end
55
+ vwo_server_url = "#{PROTOCOL}://#{HOSTNAME}#{path}"
52
56
 
53
57
  settings_file_response = ::VWO::Utils::Request.get(vwo_server_url, params)
54
58
 
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -44,6 +44,11 @@ class VWO
44
44
  )
45
45
  end
46
46
 
47
+ def update_settings_file(settings_file)
48
+ @settings_file = settings_file
49
+ process_settings_file
50
+ end
51
+
47
52
  def get_settings_file
48
53
  @settings_file
49
54
  end
@@ -0,0 +1,29 @@
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class VWO
16
+ module Services
17
+ class UsageStats
18
+ attr_reader :usage_stats
19
+ # Initialize the UsageStats
20
+ def initialize(stats, is_development_mode = false)
21
+ @usage_stats = {}
22
+ unless is_development_mode
23
+ @usage_stats = stats
24
+ @usage_stats[:_l] = 1 if @usage_stats.length > 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -142,6 +142,113 @@ class VWO
142
142
  campaign['key'] == campaign_key
143
143
  end
144
144
  end
145
+
146
+ # fetch campaigns from settings
147
+ #
148
+ # [string|array|nil] :campaign_key
149
+ # [Hash] :settings_file
150
+ # [string] :goal_identifier
151
+ # [string] :goal_type_to_track
152
+ # @return[Hash]
153
+ def get_campaigns(settings_file, campaign_key, goal_identifier, goal_type_to_track = 'ALL')
154
+ campaigns = []
155
+ if campaign_key.nil?
156
+ campaigns = get_campaigns_for_goal(settings_file, goal_identifier, goal_type_to_track)
157
+ elsif campaign_key.is_a?(Array)
158
+ campaigns = get_campaigns_from_campaign_keys(campaign_key, settings_file, goal_identifier, goal_type_to_track)
159
+ elsif campaign_key.is_a?(String)
160
+ campaign = get_campaign_for_campaign_key_and_goal(campaign_key, settings_file, goal_identifier, goal_type_to_track)
161
+ if campaign
162
+ campaigns = [campaign]
163
+ end
164
+ end
165
+ if campaigns.length() == 0
166
+ VWO::Logger.get_instance.log(
167
+ LogLevelEnum::ERROR,
168
+ format(
169
+ LogMessageEnum::ErrorMessages::NO_CAMPAIGN_FOUND,
170
+ file: FileNameEnum::CampaignUtil,
171
+ goal_identifier: goal_identifier
172
+ )
173
+ )
174
+ end
175
+ return campaigns
176
+ end
177
+
178
+ # fetch all running campaigns (having goal identifier goal_type_to_track and goal type CUSTOM|REVENUE|ALL) from settings
179
+ #
180
+ # [Hash] :settings_file
181
+ # [string] :goal_identifier
182
+ # [string] :goal_type_to_track
183
+ # @return[Hash]
184
+ def get_campaigns_for_goal(settings_file, goal_identifier, goal_type_to_track = 'ALL')
185
+ campaigns = []
186
+ if settings_file
187
+ settings_file['campaigns'].each do |campaign|
188
+ if campaign.key?(:status) && campaign[:status] != 'RUNNING'
189
+ next
190
+ end
191
+ goal = get_campaign_goal(campaign, goal_identifier)
192
+ if validate_goal(goal, goal_type_to_track)
193
+ campaigns.push(campaign)
194
+ end
195
+ end
196
+ end
197
+ campaigns
198
+ end
199
+
200
+ def validate_goal(goal, goal_type_to_track)
201
+ result = goal && (
202
+ goal_type_to_track == 'ALL' ||
203
+ (
204
+ GOAL_TYPES.has_value?(goal['type']) &&
205
+ (GOAL_TYPES.key? goal_type_to_track) &&
206
+ goal['type'] == GOAL_TYPES[goal_type_to_track]
207
+ )
208
+ )
209
+ return result
210
+ end
211
+
212
+ def get_campaigns_from_campaign_keys(campaign_keys, settings_file, goal_identifier, goal_type_to_track = 'ALL')
213
+ campaigns = []
214
+ campaign_keys.each do |campaign_key|
215
+
216
+ campaign = get_campaign_for_campaign_key_and_goal(campaign_key, settings_file, goal_identifier, goal_type_to_track)
217
+ if campaign
218
+ campaigns.push(campaign)
219
+ end
220
+ end
221
+ campaigns
222
+ end
223
+
224
+ def get_campaign_for_campaign_key_and_goal(campaign_key, settings_file, goal_identifier, goal_type_to_track)
225
+ campaign = get_running_campaign(campaign_key, settings_file)
226
+ if campaign
227
+ goal = get_campaign_goal(campaign, goal_identifier)
228
+ if validate_goal(goal, goal_type_to_track)
229
+ return campaign
230
+ end
231
+ end
232
+ nil
233
+ end
234
+
235
+ def get_running_campaign(campaign_key, settings_file)
236
+ campaign = get_campaign(settings_file, campaign_key)
237
+ if campaign.nil? || (campaign['status'] != 'RUNNING')
238
+ @logger.log(
239
+ LogLevelEnum::ERROR,
240
+ format(
241
+ LogMessageEnum::ErrorMessages::CAMPAIGN_NOT_RUNNING,
242
+ file: FILE,
243
+ campaign_key: campaign_key,
244
+ api_name: ApiMethods::TRACK
245
+ )
246
+ )
247
+ nil
248
+ end
249
+ return campaign
250
+ end
251
+
145
252
  end
146
253
  end
147
254
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -26,13 +26,36 @@ class VWO
26
26
  include VWO::Enums
27
27
  include VWO::Utils::Impression
28
28
 
29
- def get_url_params(settings_file, tag_key, tag_value, user_id)
29
+ def get_url_params(settings_file, tag_key, tag_value, user_id, sdk_key)
30
30
  url = HTTPS_PROTOCOL + ENDPOINTS::BASE_URL + ENDPOINTS::PUSH
31
31
  tag = { 'u' => {} }
32
32
  tag['u'][tag_key] = tag_value
33
33
 
34
34
  params = get_common_properties(user_id, settings_file)
35
- params.merge!('url' => url, 'tags' => JSON.generate(tag))
35
+ params.merge!('url' => url, 'tags' => JSON.generate(tag), 'env' => sdk_key)
36
+
37
+ VWO::Logger.get_instance.log(
38
+ LogLevelEnum::DEBUG,
39
+ format(
40
+ LogMessageEnum::DebugMessages::PARAMS_FOR_PUSH_CALL,
41
+ file: FileNameEnum::CustomDimensionsUtil,
42
+ properties: JSON.generate(params)
43
+ )
44
+ )
45
+ params
46
+ end
47
+
48
+ def get_batch_event_url_params(settings_file, tag_key, tag_value, user_id)
49
+ tag = { 'u' => {} }
50
+ tag['u'][tag_key] = tag_value
51
+
52
+ account_id = settings_file['accountId']
53
+ params = {
54
+ 'eT' => 3,
55
+ 't' => JSON.generate(tag),
56
+ 'u' => generator_for(user_id, account_id),
57
+ 'sId' => get_current_unix_timestamp
58
+ }
36
59
 
37
60
  VWO::Logger.get_instance.log(
38
61
  LogLevelEnum::DEBUG,
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2019-2020 Wingify Software Pvt. Ltd.
1
+ # Copyright 2019-2021 Wingify Software Pvt. Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -31,16 +31,17 @@ class VWO
31
31
 
32
32
  # Creates the impression from the arguments passed
33
33
  #
34
- # @param[Hash] :settings_file Settings file object
34
+ # @param[Hash] :settings_file Settings file object
35
35
  # @param[String] :campaign_id Campaign identifier
36
36
  # @param[String] :variation_id Variation identifier
37
37
  # @param[String] :user_id User identifier
38
+ # @param[String] :sdk_key SDK Key
38
39
  # @param[String] :goal_id Goal identifier, if building track impression
39
40
  # @param[String|Float|Integer|nil) :revenue Number value, in any representation, if building track impression
40
41
  #
41
42
  # @return[nil|Hash] None if campaign ID or variation ID is invalid,
42
43
  # Else Properties(dict)
43
- def create_impression(settings_file, campaign_id, variation_id, user_id, goal_id = nil, revenue = nil)
44
+ def create_impression(settings_file, campaign_id, variation_id, user_id, sdk_key, goal_id = nil, revenue = nil, usage_stats = {})
44
45
  return unless valid_number?(campaign_id) && valid_string?(user_id)
45
46
 
46
47
  is_track_user_api = true
@@ -51,17 +52,19 @@ class VWO
51
52
  account_id: account_id,
52
53
  experiment_id: campaign_id,
53
54
  ap: PLATFORM,
54
- uId: CGI.escape(user_id.encode('utf-8')),
55
55
  combination: variation_id,
56
56
  random: get_random_number,
57
57
  sId: get_current_unix_timestamp,
58
- u: generator_for(user_id, account_id)
58
+ u: generator_for(user_id, account_id),
59
+ env: sdk_key
59
60
  }
60
61
  # Version and SDK constants
61
62
  sdk_version = Gem.loaded_specs['vwo_sdk'] ? Gem.loaded_specs['vwo_sdk'].version : VWO::SDK_VERSION
62
63
  impression['sdk'] = 'ruby'
63
64
  impression['sdk-v'] = sdk_version
64
65
 
66
+ impression = usage_stats.merge(impression)
67
+
65
68
  url = HTTPS_PROTOCOL + ENDPOINTS::BASE_URL
66
69
  logger = VWO::Logger.get_instance
67
70
 
@@ -107,9 +110,57 @@ class VWO
107
110
  'ap' => PLATFORM,
108
111
  'sId' => get_current_unix_timestamp,
109
112
  'u' => generator_for(user_id, account_id),
110
- 'account_id' => account_id,
111
- 'uId' => CGI.escape(user_id.encode('utf-8'))
113
+ 'account_id' => account_id
114
+ }
115
+ end
116
+
117
+ # Creates properties for the bulk impression event
118
+ #
119
+ # @param[Hash] :settings_file Settings file object
120
+ # @param[String] :campaign_id Campaign identifier
121
+ # @param[String] :variation_id Variation identifier
122
+ # @param[String] :user_id User identifier
123
+ # @param[String] :sdk_key SDK Key
124
+ # @param[String] :goal_id Goal identifier, if building track impression
125
+ # @param[String|Float|Integer|nil) :revenue Number value, in any representation, if building track impression
126
+ #
127
+ # @return[nil|Hash] None if campaign ID or variation ID is invalid,
128
+ # Else Properties(dict)
129
+ def create_bulk_event_impression(settings_file, campaign_id, variation_id, user_id, goal_id = nil, revenue = nil)
130
+ return unless valid_number?(campaign_id) && valid_string?(user_id)
131
+ is_track_user_api = true
132
+ is_track_user_api = false unless goal_id.nil?
133
+ account_id = settings_file['accountId']
134
+ impression = {
135
+ eT: is_track_user_api ? 1 : 2,
136
+ e: campaign_id,
137
+ c: variation_id,
138
+ u: generator_for(user_id, account_id),
139
+ sId: get_current_unix_timestamp
112
140
  }
141
+ logger = VWO::Logger.get_instance
142
+ if is_track_user_api
143
+ logger.log(
144
+ LogLevelEnum::DEBUG,
145
+ format(
146
+ LogMessageEnum::DebugMessages::IMPRESSION_FOR_TRACK_USER,
147
+ file: FileNameEnum::ImpressionUtil,
148
+ properties: JSON.generate(impression)
149
+ )
150
+ )
151
+ else
152
+ impression['g'] = goal_id
153
+ impression['r'] = revenue if revenue
154
+ logger.log(
155
+ LogLevelEnum::DEBUG,
156
+ format(
157
+ LogMessageEnum::DebugMessages::IMPRESSION_FOR_TRACK_GOAL,
158
+ file: FileNameEnum::ImpressionUtil,
159
+ properties: JSON.generate(impression)
160
+ )
161
+ )
162
+ end
163
+ impression
113
164
  end
114
165
  end
115
166
  end