vwo-fme-ruby-sdk 1.3.2 → 1.4.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.
- checksums.yaml +4 -4
- data/lib/vwo/api/set_attribute.rb +3 -8
- data/lib/vwo/api/track_event.rb +2 -5
- data/lib/vwo/constants/constants.rb +3 -1
- data/lib/vwo/enums/event_enum.rb +2 -1
- data/lib/vwo/models/schemas/settings_schema_validation.rb +1 -0
- data/lib/vwo/packages/logger/core/log_manager.rb +3 -1
- data/lib/vwo/services/settings_service.rb +8 -1
- data/lib/vwo/utils/event_util.rb +36 -0
- data/lib/vwo/utils/impression_util.rb +0 -2
- data/lib/vwo/utils/network_util.rb +69 -15
- data/lib/vwo/vwo_client.rb +1 -1
- data/lib/vwo.rb +25 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46ef28eb680c91f4a2009e0fdff9053a4c2f82cfacbe2b09c5a3359b469a104a
|
4
|
+
data.tar.gz: a5aeb2e3856e53a62f8c52ff1da83c7396260f50087441f2537b94319459013f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 216b54b6567c982b2c6392c1bb52a940cb0eb083604f7bcc8040e1017acf06a8da1438a665706b9e0f618e57ccbc7146f8a59cda2bce8eba6c8fb7fbcb05af96
|
7
|
+
data.tar.gz: 5ed4c55969fe455f57b946b67314382a2f50534fdc4e62948a54b88ed0a81bb9c94b5c0abe01b24c255bb2f15c449893545865a3a4ad8e8b7467ffd5d43e24bc
|
@@ -15,28 +15,24 @@
|
|
15
15
|
require_relative '../models/user/context_model'
|
16
16
|
require_relative '../enums/event_enum'
|
17
17
|
require_relative '../utils/network_util'
|
18
|
-
require_relative '../models/settings/settings_model'
|
19
18
|
require_relative '../services/batch_event_queue'
|
20
19
|
|
21
20
|
class SetAttributeApi
|
22
21
|
# Sets multiple attributes for a user in a single network call.
|
23
|
-
# @param settings [SettingsModel] Configuration settings.
|
24
22
|
# @param attributes [Hash] Key-value map of attributes.
|
25
23
|
# @param context [ContextModel] Context containing user information.
|
26
|
-
def set_attribute(
|
27
|
-
create_impression_for_attributes(
|
24
|
+
def set_attribute(attributes, context)
|
25
|
+
create_impression_for_attributes(attributes, context)
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
31
29
|
|
32
30
|
# Creates an impression for multiple user attributes and sends it to the server.
|
33
|
-
# @param settings [SettingsModel] Configuration settings.
|
34
31
|
# @param attributes [Hash] Key-value map of attributes.
|
35
32
|
# @param context [ContextModel] Context containing user information.
|
36
|
-
def create_impression_for_attributes(
|
33
|
+
def create_impression_for_attributes(attributes, context)
|
37
34
|
# Retrieve base properties for the event
|
38
35
|
properties = NetworkUtil.get_events_base_properties(
|
39
|
-
settings,
|
40
36
|
EventEnum::VWO_SYNC_VISITOR_PROP,
|
41
37
|
URI.encode_www_form_component(context.user_agent),
|
42
38
|
context.ip_address
|
@@ -44,7 +40,6 @@ class SetAttributeApi
|
|
44
40
|
|
45
41
|
# Construct payload data for multiple attributes
|
46
42
|
payload = NetworkUtil.get_attribute_payload_data(
|
47
|
-
settings,
|
48
43
|
context.id,
|
49
44
|
EventEnum::VWO_SYNC_VISITOR_PROP,
|
50
45
|
attributes,
|
data/lib/vwo/api/track_event.rb
CHANGED
@@ -32,7 +32,7 @@ class TrackApi
|
|
32
32
|
def track(settings, event_name, context, event_properties, hooks_service)
|
33
33
|
if does_event_belong_to_any_feature(event_name, settings)
|
34
34
|
# Create an impression for the track event
|
35
|
-
create_impression_for_track(
|
35
|
+
create_impression_for_track(event_name, context, event_properties)
|
36
36
|
|
37
37
|
# Set and execute integration callback for the track event
|
38
38
|
hooks_service.set({ event_name: event_name, api: ApiEnum::TRACK })
|
@@ -50,14 +50,12 @@ class TrackApi
|
|
50
50
|
private
|
51
51
|
|
52
52
|
# Creates an impression for a track event and sends it via a POST API request.
|
53
|
-
# @param settings [SettingsModel] Configuration settings.
|
54
53
|
# @param event_name [String] Name of the event to track.
|
55
54
|
# @param context [ContextModel] User details.
|
56
55
|
# @param event_properties [Hash] Properties associated with the event.
|
57
|
-
def create_impression_for_track(
|
56
|
+
def create_impression_for_track(event_name, context, event_properties)
|
58
57
|
# Get base properties for the event
|
59
58
|
properties = NetworkUtil.get_events_base_properties(
|
60
|
-
settings,
|
61
59
|
event_name,
|
62
60
|
URI.encode_www_form_component(context.user_agent),
|
63
61
|
context.ip_address
|
@@ -65,7 +63,6 @@ class TrackApi
|
|
65
63
|
|
66
64
|
# Prepare the payload for the track goal
|
67
65
|
payload = NetworkUtil.get_track_goal_payload_data(
|
68
|
-
settings,
|
69
66
|
context.id,
|
70
67
|
event_name,
|
71
68
|
event_properties,
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# Define the Constants module
|
18
18
|
module Constants
|
19
19
|
SDK_NAME = 'vwo-fme-ruby-sdk'.freeze
|
20
|
-
SDK_VERSION = '1.
|
20
|
+
SDK_VERSION = '1.4.0'.freeze
|
21
21
|
|
22
22
|
MAX_TRAFFIC_PERCENT = 100
|
23
23
|
MAX_TRAFFIC_VALUE = 10_000
|
@@ -55,4 +55,6 @@ module Constants
|
|
55
55
|
SHOULD_USE_THREADING = true
|
56
56
|
MAX_POOL_SIZE = 5
|
57
57
|
MAX_QUEUE_SIZE = 10000
|
58
|
+
|
59
|
+
PRODUCT_NAME = 'fme'.freeze
|
58
60
|
end
|
data/lib/vwo/enums/event_enum.rb
CHANGED
@@ -17,6 +17,7 @@ require 'securerandom'
|
|
17
17
|
require_relative '../logger'
|
18
18
|
require_relative 'transport_manager'
|
19
19
|
require_relative '../transports/console_transport'
|
20
|
+
require_relative '../../../enums/log_level_enum'
|
20
21
|
|
21
22
|
class LogManager < VWOLogger
|
22
23
|
@instance = nil
|
@@ -62,8 +63,9 @@ class LogManager < VWOLogger
|
|
62
63
|
@transport_manager.log('WARN', message)
|
63
64
|
end
|
64
65
|
|
65
|
-
def error(message)
|
66
|
+
def error(message, extraData = {})
|
66
67
|
@transport_manager.log('ERROR', message)
|
68
|
+
# sendLogToVWO(message, LogLevelEnum::ERROR, extraData)
|
67
69
|
end
|
68
70
|
|
69
71
|
private
|
@@ -23,7 +23,7 @@ require_relative '../enums/log_level_enum'
|
|
23
23
|
require_relative '../models/schemas/settings_schema_validation'
|
24
24
|
|
25
25
|
class SettingsService
|
26
|
-
attr_accessor :sdk_key, :account_id, :expiry, :network_timeout, :hostname, :port, :protocol, :is_gateway_service_provided, :is_settings_valid
|
26
|
+
attr_accessor :sdk_key, :account_id, :expiry, :network_timeout, :hostname, :port, :protocol, :is_gateway_service_provided, :is_settings_valid, :settings_fetch_time
|
27
27
|
|
28
28
|
class << self
|
29
29
|
attr_accessor :instance
|
@@ -93,8 +93,15 @@ class SettingsService
|
|
93
93
|
request = RequestModel.new(@hostname, "GET", path, options, nil, nil, @protocol, @port)
|
94
94
|
request.set_timeout(@network_timeout)
|
95
95
|
|
96
|
+
# store the current time in milliseconds
|
97
|
+
settings_fetch_start_time = (Time.now.to_f * 1000).to_i
|
98
|
+
|
96
99
|
begin
|
97
100
|
response = network_instance.get(request)
|
101
|
+
# calculate the time taken to fetch the settings
|
102
|
+
settings_fetch_end_time = (Time.now.to_f * 1000).to_i
|
103
|
+
time_taken = settings_fetch_end_time - settings_fetch_start_time
|
104
|
+
@settings_fetch_time = time_taken.to_s
|
98
105
|
response.get_data
|
99
106
|
rescue => e
|
100
107
|
LoggerService.log(LogLevelEnum::ERROR, "Error fetching settings: #{e.message}", nil)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright 2024-2025 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
|
+
require_relative './network_util'
|
16
|
+
require_relative '../enums/event_enum'
|
17
|
+
require_relative '../services/batch_event_queue'
|
18
|
+
|
19
|
+
# Sends an init called event to VWO.
|
20
|
+
# This event is triggered when the init function is called.
|
21
|
+
# @param settings_fetch_time [Number] Time taken to fetch settings in milliseconds.
|
22
|
+
# @param sdk_init_time [Number] Time taken to initialize the SDK in milliseconds.
|
23
|
+
def send_sdk_init_event(settings_fetch_time, sdk_init_time)
|
24
|
+
# Get base properties for the event
|
25
|
+
properties = NetworkUtil.get_events_base_properties(EventEnum::VWO_INIT_CALLED)
|
26
|
+
payload = NetworkUtil.get_sdk_init_event_payload(EventEnum::VWO_INIT_CALLED, settings_fetch_time, sdk_init_time)
|
27
|
+
|
28
|
+
# check if batching is enabled
|
29
|
+
if BatchEventsQueue.instance
|
30
|
+
# add the payload to the batch events queue
|
31
|
+
BatchEventsQueue.instance.enqueue(payload)
|
32
|
+
else
|
33
|
+
# Send the constructed payload via POST request
|
34
|
+
NetworkUtil.send_event(properties, payload)
|
35
|
+
end
|
36
|
+
end
|
@@ -28,7 +28,6 @@ require_relative '../services/batch_event_queue'
|
|
28
28
|
def create_and_send_impression_for_variation_shown(settings, campaign_id, variation_id, context)
|
29
29
|
# Get base properties for the event
|
30
30
|
properties = NetworkUtil.get_events_base_properties(
|
31
|
-
settings,
|
32
31
|
EventEnum::VWO_VARIATION_SHOWN,
|
33
32
|
URI.encode_www_form_component(context.get_user_agent), # Encode user agent for URL safety
|
34
33
|
context.get_ip_address
|
@@ -36,7 +35,6 @@ def create_and_send_impression_for_variation_shown(settings, campaign_id, variat
|
|
36
35
|
|
37
36
|
# Construct payload data for tracking the user
|
38
37
|
payload = NetworkUtil.get_track_user_payload_data(
|
39
|
-
settings,
|
40
38
|
context.get_id,
|
41
39
|
EventEnum::VWO_VARIATION_SHOWN,
|
42
40
|
campaign_id,
|
@@ -80,11 +80,11 @@ class NetworkUtil
|
|
80
80
|
end
|
81
81
|
|
82
82
|
# Builds generic properties for different tracking calls
|
83
|
-
def get_events_base_properties(
|
84
|
-
sdk_key =
|
83
|
+
def get_events_base_properties(event_name, visitor_user_agent = '', ip_address = '')
|
84
|
+
sdk_key = SettingsService.instance.sdk_key || ''
|
85
85
|
{
|
86
86
|
en: event_name,
|
87
|
-
a:
|
87
|
+
a: SettingsService.instance.account_id,
|
88
88
|
env: sdk_key,
|
89
89
|
eTime: get_current_unix_timestamp_in_millis,
|
90
90
|
random: get_random_number,
|
@@ -96,9 +96,9 @@ class NetworkUtil
|
|
96
96
|
end
|
97
97
|
|
98
98
|
# Builds base payload for tracking events
|
99
|
-
def _get_event_base_payload(
|
100
|
-
uuid = UUIDUtil.get_uuid(user_id.to_s,
|
101
|
-
sdk_key =
|
99
|
+
def _get_event_base_payload(user_id, event_name, visitor_user_agent = '', ip_address = '')
|
100
|
+
uuid = UUIDUtil.get_uuid(user_id.to_s, SettingsService.instance.account_id)
|
101
|
+
sdk_key = SettingsService.instance.sdk_key
|
102
102
|
|
103
103
|
{
|
104
104
|
d: {
|
@@ -124,8 +124,8 @@ class NetworkUtil
|
|
124
124
|
end
|
125
125
|
|
126
126
|
# Builds track-user payload data
|
127
|
-
def get_track_user_payload_data(
|
128
|
-
properties = _get_event_base_payload(
|
127
|
+
def get_track_user_payload_data(user_id, event_name, campaign_id, variation_id, visitor_user_agent = '', ip_address = '')
|
128
|
+
properties = _get_event_base_payload(user_id, event_name, visitor_user_agent, ip_address)
|
129
129
|
properties[:d][:event][:props][:id] = campaign_id
|
130
130
|
properties[:d][:event][:props][:variation] = variation_id
|
131
131
|
properties[:d][:event][:props][:isFirst] = 1
|
@@ -141,7 +141,7 @@ class NetworkUtil
|
|
141
141
|
end
|
142
142
|
|
143
143
|
LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_TRACK_USER", {
|
144
|
-
accountId:
|
144
|
+
accountId: SettingsService.instance.account_id,
|
145
145
|
userId: user_id,
|
146
146
|
campaignId: campaign_id
|
147
147
|
})
|
@@ -150,8 +150,8 @@ class NetworkUtil
|
|
150
150
|
end
|
151
151
|
|
152
152
|
# Constructs payload for tracking goals with custom event properties
|
153
|
-
def get_track_goal_payload_data(
|
154
|
-
properties = _get_event_base_payload(
|
153
|
+
def get_track_goal_payload_data(user_id, event_name, event_properties, visitor_user_agent = '', ip_address = '')
|
154
|
+
properties = _get_event_base_payload(user_id, event_name, visitor_user_agent, ip_address)
|
155
155
|
properties[:d][:event][:props][:isCustomEvent] = true
|
156
156
|
|
157
157
|
if SettingsService.instance.is_gateway_service_provided
|
@@ -165,15 +165,15 @@ class NetworkUtil
|
|
165
165
|
|
166
166
|
LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_TRACK_GOAL", {
|
167
167
|
eventName: event_name,
|
168
|
-
accountId:
|
168
|
+
accountId: SettingsService.instance.account_id,
|
169
169
|
userId: user_id
|
170
170
|
})
|
171
171
|
|
172
172
|
properties
|
173
173
|
end
|
174
174
|
|
175
|
-
def get_attribute_payload_data(
|
176
|
-
properties = _get_event_base_payload(
|
175
|
+
def get_attribute_payload_data(user_id, event_name, event_properties, visitor_user_agent = '', ip_address = '')
|
176
|
+
properties = _get_event_base_payload(user_id, event_name, visitor_user_agent, ip_address)
|
177
177
|
properties[:d][:event][:props][:isCustomEvent] = true
|
178
178
|
|
179
179
|
if event_properties.is_a?(Hash) && !event_properties.empty?
|
@@ -182,12 +182,31 @@ class NetworkUtil
|
|
182
182
|
|
183
183
|
LoggerService.log(LogLevelEnum::DEBUG, "IMPRESSION_FOR_SYNC_VISITOR_PROP", {
|
184
184
|
eventName: event_name,
|
185
|
-
accountId:
|
185
|
+
accountId: SettingsService.instance.account_id,
|
186
186
|
userId: user_id
|
187
187
|
})
|
188
188
|
properties
|
189
189
|
end
|
190
190
|
|
191
|
+
# Constructs the payload for init called event.
|
192
|
+
# @param event_name - The name of the event.
|
193
|
+
# @param settings_fetch_time - Time taken to fetch settings in milliseconds.
|
194
|
+
# @param sdk_init_time - Time taken to initialize the SDK in milliseconds.
|
195
|
+
# @returns The constructed payload with required fields.
|
196
|
+
def get_sdk_init_event_payload(event_name, settings_fetch_time, sdk_init_time)
|
197
|
+
user_id = SettingsService.instance.account_id + "_" + SettingsService.instance.sdk_key
|
198
|
+
properties = _get_event_base_payload(user_id, event_name, nil, nil)
|
199
|
+
properties[:d][:event][:props][:vwo_fs_environment] = SettingsService.instance.sdk_key
|
200
|
+
properties[:d][:event][:props][:product] = Constants::PRODUCT_NAME
|
201
|
+
data = {
|
202
|
+
"isSDKInitialized": true,
|
203
|
+
"settingsFetchTime": settings_fetch_time,
|
204
|
+
"sdkInitTime": sdk_init_time
|
205
|
+
}
|
206
|
+
properties[:d][:event][:props][:data] = data
|
207
|
+
properties
|
208
|
+
end
|
209
|
+
|
191
210
|
# Sends a POST API request with given properties and payload
|
192
211
|
def send_post_api_request(properties, payload)
|
193
212
|
network_instance = NetworkManager.instance
|
@@ -230,6 +249,41 @@ class NetworkUtil
|
|
230
249
|
end
|
231
250
|
end
|
232
251
|
|
252
|
+
# Sends an event to VWO (generic event sender).
|
253
|
+
# @param properties - Query parameters for the request.
|
254
|
+
# @param payload - The payload for the request.
|
255
|
+
# @param event_name - The name of the event to send.
|
256
|
+
def send_event(properties, payload)
|
257
|
+
network_instance = NetworkManager.instance
|
258
|
+
headers = {}
|
259
|
+
headers[HeadersEnum::USER_AGENT] = payload[:d][:visitor_ua] if payload[:d][:visitor_ua]
|
260
|
+
headers[HeadersEnum::IP] = payload[:d][:visitor_ip] if payload[:d][:visitor_ip]
|
261
|
+
|
262
|
+
request = RequestModel.new(
|
263
|
+
UrlUtil.get_base_url,
|
264
|
+
HttpMethodEnum::POST,
|
265
|
+
UrlEnum::EVENTS,
|
266
|
+
properties,
|
267
|
+
payload,
|
268
|
+
headers,
|
269
|
+
SettingsService.instance.protocol,
|
270
|
+
SettingsService.instance.port
|
271
|
+
)
|
272
|
+
|
273
|
+
begin
|
274
|
+
if network_instance.get_client.get_should_use_threading
|
275
|
+
network_instance.get_client.get_thread_pool.post {
|
276
|
+
response = network_instance.post(request)
|
277
|
+
response
|
278
|
+
}
|
279
|
+
else
|
280
|
+
response = network_instance.post(request)
|
281
|
+
response
|
282
|
+
end
|
283
|
+
rescue ResponseModel => err
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
233
287
|
# Sends a GET API request to the specified endpoint with given properties
|
234
288
|
def send_get_api_request(properties, endpoint)
|
235
289
|
network_instance = NetworkManager.instance
|
data/lib/vwo/vwo_client.rb
CHANGED
@@ -146,7 +146,7 @@ class VWOClient
|
|
146
146
|
end
|
147
147
|
|
148
148
|
context_model = ContextModel.new.model_from_dictionary(context)
|
149
|
-
SetAttributeApi.new.set_attribute(
|
149
|
+
SetAttributeApi.new.set_attribute(attributes, context_model)
|
150
150
|
rescue StandardError => e
|
151
151
|
LoggerService.log(LogLevelEnum::ERROR, "API_THROW_ERROR", {apiName: api_name, err: e.message})
|
152
152
|
end
|
data/lib/vwo.rb
CHANGED
@@ -16,6 +16,8 @@ require 'json'
|
|
16
16
|
require 'uri'
|
17
17
|
require_relative 'vwo/vwo_builder'
|
18
18
|
require_relative 'vwo/vwo_client'
|
19
|
+
require_relative 'vwo/utils/event_util'
|
20
|
+
require_relative 'vwo/services/settings_service'
|
19
21
|
|
20
22
|
class VWO
|
21
23
|
@@vwo_builder = nil
|
@@ -67,7 +69,30 @@ class VWO
|
|
67
69
|
puts "[ERROR]: VWO-SDK: Please provide VWO account ID in the options and should be a of type string|number"
|
68
70
|
end
|
69
71
|
|
72
|
+
# store the current time in milliseconds
|
73
|
+
sdk_init_start_time = (Time.now.to_f * 1000).to_i
|
74
|
+
# initialize the vwo instance
|
70
75
|
new(options)
|
76
|
+
# store the time after initializing the vwo instance in milliseconds
|
77
|
+
sdk_init_end_time = (Time.now.to_f * 1000).to_i
|
78
|
+
# calculate the time taken for initializing the vwo instance
|
79
|
+
time_taken_for_init = sdk_init_end_time - sdk_init_start_time
|
80
|
+
# get sdkMetaInfo from settings file to check if the sdk was initialized earlier
|
81
|
+
sdk_meta_info = nil
|
82
|
+
was_initialized_earlier = false
|
83
|
+
|
84
|
+
begin
|
85
|
+
if @@instance && @@instance.original_settings && @@instance.original_settings.is_a?(Hash)
|
86
|
+
sdk_meta_info = @@instance.original_settings["sdkMetaInfo"]
|
87
|
+
was_initialized_earlier = sdk_meta_info && sdk_meta_info.is_a?(Hash) ? sdk_meta_info["wasInitializedEarlier"] : false
|
88
|
+
end
|
89
|
+
rescue StandardError => e
|
90
|
+
was_initialized_earlier = false
|
91
|
+
end
|
92
|
+
if !was_initialized_earlier && SettingsService.instance.is_settings_valid
|
93
|
+
# send the sdk init info to vwo server
|
94
|
+
send_sdk_init_event(SettingsService.instance.settings_fetch_time, time_taken_for_init.to_s)
|
95
|
+
end
|
71
96
|
@@instance
|
72
97
|
rescue StandardError => e
|
73
98
|
puts "[ERROR]: VWO-SDK: Got error while initializing VWO: #{e.message}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vwo-fme-ruby-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VWO
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07
|
11
|
+
date: 2025-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uuidtools
|
@@ -211,6 +211,7 @@ files:
|
|
211
211
|
- lib/vwo/utils/campaign_util.rb
|
212
212
|
- lib/vwo/utils/data_type_util.rb
|
213
213
|
- lib/vwo/utils/decision_util.rb
|
214
|
+
- lib/vwo/utils/event_util.rb
|
214
215
|
- lib/vwo/utils/function_util.rb
|
215
216
|
- lib/vwo/utils/gateway_service_util.rb
|
216
217
|
- lib/vwo/utils/impression_util.rb
|