vwo-sdk 1.36.0 → 1.37.1
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/constants.rb +2 -2
- data/lib/vwo/core/bucketer.rb +18 -26
- data/lib/vwo/core/variation_decider.rb +216 -220
- data/lib/vwo/enums.rb +16 -19
- data/lib/vwo/logger.rb +2 -3
- data/lib/vwo/schemas/settings_file.rb +6 -6
- data/lib/vwo/services/batch_events_dispatcher.rb +19 -21
- data/lib/vwo/services/batch_events_queue.rb +27 -43
- data/lib/vwo/services/event_dispatcher.rb +31 -21
- data/lib/vwo/services/hooks_manager.rb +8 -12
- data/lib/vwo/services/segment_evaluator.rb +7 -6
- data/lib/vwo/services/settings_file_manager.rb +5 -5
- data/lib/vwo/services/settings_file_processor.rb +1 -1
- data/lib/vwo/services/usage_stats.rb +5 -4
- data/lib/vwo/utils/campaign.rb +37 -39
- data/lib/vwo/utils/custom_dimensions.rb +2 -2
- data/lib/vwo/utils/data_location_manager.rb +2 -9
- data/lib/vwo/utils/feature.rb +2 -2
- data/lib/vwo/utils/impression.rb +29 -37
- data/lib/vwo/utils/log_message.rb +23 -30
- data/lib/vwo/utils/request.rb +7 -9
- data/lib/vwo/utils/utility.rb +44 -34
- data/lib/vwo/utils/validations.rb +72 -5
- data/lib/vwo.rb +197 -344
- metadata +8 -8
data/lib/vwo.rb
CHANGED
@@ -36,6 +36,7 @@ require_relative 'vwo/services/usage_stats'
|
|
36
36
|
class VWO
|
37
37
|
attr_accessor :is_instance_valid, :logging, :settings_file_manager, :variation_decider
|
38
38
|
attr_reader :usage_stats
|
39
|
+
|
39
40
|
include Enums
|
40
41
|
include Utils::Validations
|
41
42
|
include Utils::Feature
|
@@ -128,34 +129,21 @@ class VWO
|
|
128
129
|
@is_instance_valid = true
|
129
130
|
@config = VWO::Services::SettingsFileProcessor.new(get_settings)
|
130
131
|
|
131
|
-
#Process the settings file
|
132
|
+
# Process the settings file
|
132
133
|
@config.process_settings_file
|
133
134
|
@settings_file = @config.get_settings_file
|
134
|
-
DataLocationManager.get_instance
|
135
|
+
DataLocationManager.get_instance.set_settings(@settings_file)
|
135
136
|
|
136
137
|
@usage_stats = VWO::Services::UsageStats.new(usage_stats, @is_development_mode)
|
137
138
|
|
138
139
|
if options.key?(:batch_events)
|
139
140
|
if options[:batch_events].is_a?(Hash)
|
140
|
-
unless
|
141
|
+
unless valid_batch_event_settings(options[:batch_events], ApiMethods::LAUNCH)
|
141
142
|
@is_instance_valid = false
|
142
143
|
return
|
143
144
|
end
|
144
145
|
@batch_event_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
145
|
-
|
146
|
-
@batch_event_dispatcher.dispatch(
|
147
|
-
{
|
148
|
-
ev: events
|
149
|
-
},
|
150
|
-
callback,
|
151
|
-
{
|
152
|
-
a: @account_id,
|
153
|
-
sd: SDK_NAME,
|
154
|
-
sv: SDK_VERSION,
|
155
|
-
env: @sdk_key
|
156
|
-
}.merge(@usage_stats.usage_stats)
|
157
|
-
)
|
158
|
-
end
|
146
|
+
|
159
147
|
@batch_events_queue = VWO::Services::BatchEventsQueue.new(
|
160
148
|
options[:batch_events].merge(
|
161
149
|
{
|
@@ -192,7 +180,22 @@ class VWO
|
|
192
180
|
@logger.log(
|
193
181
|
LogLevelEnum::INFO,
|
194
182
|
'SDK_INITIALIZED',
|
195
|
-
{'{file}' => FILE}
|
183
|
+
{ '{file}' => FILE }
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
def dispatcher(events, callback)
|
188
|
+
@batch_event_dispatcher.dispatch(
|
189
|
+
{
|
190
|
+
ev: events
|
191
|
+
},
|
192
|
+
callback,
|
193
|
+
{
|
194
|
+
a: @account_id,
|
195
|
+
sd: SDK_NAME,
|
196
|
+
sv: SDK_VERSION,
|
197
|
+
env: @sdk_key
|
198
|
+
}.merge(@usage_stats.usage_stats)
|
196
199
|
)
|
197
200
|
end
|
198
201
|
|
@@ -210,9 +213,7 @@ class VWO
|
|
210
213
|
# VWO get_settings method to get settings for a particular account_id
|
211
214
|
def get_and_update_settings_file
|
212
215
|
@logger.set_api_name(ApiMethods::GET_AND_UPDATE_SETTINGS_FILE)
|
213
|
-
if
|
214
|
-
return false
|
215
|
-
end
|
216
|
+
return false if opted_out?(ApiMethods::GET_AND_UPDATE_SETTINGS_FILE)
|
216
217
|
|
217
218
|
unless @is_instance_valid
|
218
219
|
@logger.log(
|
@@ -245,7 +246,7 @@ class VWO
|
|
245
246
|
rescue StandardError => e
|
246
247
|
@logger.log(
|
247
248
|
LogLevelEnum::ERROR,
|
248
|
-
|
249
|
+
"({file}): {api} API error: #{e.message}",
|
249
250
|
{
|
250
251
|
'{file}' => FILE,
|
251
252
|
'{api}' => ApiMethods::GET_AND_UPDATE_SETTINGS_FILE
|
@@ -273,9 +274,7 @@ class VWO
|
|
273
274
|
|
274
275
|
def activate(campaign_key, user_id, options = {})
|
275
276
|
@logger.set_api_name(ApiMethods::ACTIVATE)
|
276
|
-
if
|
277
|
-
return nil
|
278
|
-
end
|
277
|
+
return nil if opted_out?(ApiMethods::ACTIVATE)
|
279
278
|
|
280
279
|
unless @is_instance_valid
|
281
280
|
@logger.log(
|
@@ -296,7 +295,7 @@ class VWO
|
|
296
295
|
|
297
296
|
# Validate input parameters
|
298
297
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
299
|
-
|
298
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
300
299
|
@logger.log(
|
301
300
|
LogLevelEnum::ERROR,
|
302
301
|
'API_BAD_PARAMETERS',
|
@@ -339,7 +338,7 @@ class VWO
|
|
339
338
|
'{api}' => ApiMethods::ACTIVATE,
|
340
339
|
'{userId}' => user_id,
|
341
340
|
'{campaignKey}' => campaign_key,
|
342
|
-
'{campaignType}' => campaign_type
|
341
|
+
'{campaignType}' => campaign_type
|
343
342
|
}
|
344
343
|
)
|
345
344
|
return
|
@@ -358,11 +357,9 @@ class VWO
|
|
358
357
|
)
|
359
358
|
|
360
359
|
# Check if variation_name has been assigned
|
361
|
-
if variation.nil?
|
362
|
-
return
|
363
|
-
end
|
360
|
+
return if variation.nil?
|
364
361
|
|
365
|
-
if
|
362
|
+
if eligible_to_send_impression?
|
366
363
|
if defined?(@batch_events)
|
367
364
|
impression = create_bulk_event_impression(
|
368
365
|
@settings_file,
|
@@ -371,7 +368,7 @@ class VWO
|
|
371
368
|
user_id
|
372
369
|
)
|
373
370
|
@batch_events_queue.enqueue(impression)
|
374
|
-
elsif
|
371
|
+
elsif event_arch_enabled?
|
375
372
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_VARIATION_SHOWN, @usage_stats.usage_stats)
|
376
373
|
payload = get_track_user_payload_data(@settings_file, user_id, EventEnum::VWO_VARIATION_SHOWN, campaign['id'], variation['id'])
|
377
374
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
@@ -387,18 +384,8 @@ class VWO
|
|
387
384
|
nil, # revenue
|
388
385
|
usage_stats: @usage_stats.usage_stats
|
389
386
|
)
|
390
|
-
|
391
|
-
|
392
|
-
LogLevelEnum::INFO,
|
393
|
-
'IMPRESSION_SUCCESS',
|
394
|
-
{
|
395
|
-
'{file}' => FILE,
|
396
|
-
'{mainKeys}' => JSON.generate({'campaignId' => campaign['id'], 'variationId' => variation['id']}),
|
397
|
-
'{accountId}' => @account_id,
|
398
|
-
'{endPoint}' => EVENTS::TRACK_USER
|
399
|
-
}
|
400
|
-
)
|
401
|
-
end
|
387
|
+
main_keys = { 'campaignId' => campaign['id'], 'variationId' => variation['id'] }
|
388
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_USER)
|
402
389
|
end
|
403
390
|
else
|
404
391
|
@logger.log(
|
@@ -416,7 +403,7 @@ class VWO
|
|
416
403
|
rescue StandardError => e
|
417
404
|
@logger.log(
|
418
405
|
LogLevelEnum::ERROR,
|
419
|
-
|
406
|
+
"({file}): {api} API error: #{e.message}",
|
420
407
|
{
|
421
408
|
'{file}' => FILE,
|
422
409
|
'{api}' => ApiMethods::ACTIVATE
|
@@ -444,9 +431,7 @@ class VWO
|
|
444
431
|
#
|
445
432
|
def get_variation_name(campaign_key, user_id, options = {})
|
446
433
|
@logger.set_api_name(ApiMethods::GET_VARIATION_NAME)
|
447
|
-
if
|
448
|
-
return nil
|
449
|
-
end
|
434
|
+
return nil if opted_out?(ApiMethods::GET_VARIATION_NAME)
|
450
435
|
|
451
436
|
unless @is_instance_valid
|
452
437
|
@logger.log(
|
@@ -466,7 +451,7 @@ class VWO
|
|
466
451
|
|
467
452
|
# Validate input parameters
|
468
453
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
469
|
-
|
454
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
470
455
|
@logger.log(
|
471
456
|
LogLevelEnum::ERROR,
|
472
457
|
'API_BAD_PARAMETERS',
|
@@ -506,7 +491,23 @@ class VWO
|
|
506
491
|
'{api}' => ApiMethods::GET_VARIATION_NAME,
|
507
492
|
'{userId}' => user_id,
|
508
493
|
'{campaignKey}' => campaign_key,
|
509
|
-
'{campaignType}' => campaign_type
|
494
|
+
'{campaignType}' => campaign_type
|
495
|
+
}
|
496
|
+
)
|
497
|
+
return
|
498
|
+
end
|
499
|
+
|
500
|
+
case campaign_type
|
501
|
+
when CampaignTypes::FEATURE_ROLLOUT
|
502
|
+
@logger.log(
|
503
|
+
LogLevelEnum::ERROR,
|
504
|
+
'API_NOT_APPLICABLE',
|
505
|
+
{
|
506
|
+
'{file}' => FILE,
|
507
|
+
'{api}' => ApiMethods::GET_VARIATION_NAME,
|
508
|
+
'{userId}' => user_id,
|
509
|
+
'{campaignKey}' => campaign_key,
|
510
|
+
'{campaignType}' => campaign_type
|
510
511
|
}
|
511
512
|
)
|
512
513
|
return
|
@@ -515,15 +516,13 @@ class VWO
|
|
515
516
|
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::GET_VARIATION_NAME, campaign_key, custom_variables, variation_targeting_variables)
|
516
517
|
|
517
518
|
# Check if variation_name has been assigned
|
518
|
-
unless valid_value?(variation)
|
519
|
-
return
|
520
|
-
end
|
519
|
+
return unless valid_value?(variation)
|
521
520
|
|
522
521
|
variation['name']
|
523
522
|
rescue StandardError => e
|
524
523
|
@logger.log(
|
525
524
|
LogLevelEnum::ERROR,
|
526
|
-
|
525
|
+
"({file}): {api} API error: #{e.message}",
|
527
526
|
{
|
528
527
|
'{file}' => FILE,
|
529
528
|
'{api}' => ApiMethods::GET_VARIATION_NAME
|
@@ -543,15 +542,12 @@ class VWO
|
|
543
542
|
# @param[String] :campaign_key Unique campaign key
|
544
543
|
# @param[String] :user_id ID assigned to a user
|
545
544
|
# @param[String] :goal_identifier Unique campaign's goal identifier
|
546
|
-
# @param[Hash] :options
|
547
|
-
# @param[Numeric|String] :revenue_value It is the revenue generated on triggering the goal
|
545
|
+
# @param[Hash] :options Contains revenue value and custom variables
|
548
546
|
#
|
549
547
|
|
550
548
|
def track(campaign_key, user_id, goal_identifier, options = {})
|
551
549
|
@logger.set_api_name(ApiMethods::TRACK)
|
552
|
-
if
|
553
|
-
return false
|
554
|
-
end
|
550
|
+
return false if opted_out?(ApiMethods::TRACK)
|
555
551
|
|
556
552
|
unless @is_instance_valid
|
557
553
|
@logger.log(
|
@@ -572,168 +568,59 @@ class VWO
|
|
572
568
|
goal_type_to_track = get_goal_type_to_track(options)
|
573
569
|
|
574
570
|
# Check for valid args
|
575
|
-
|
576
|
-
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables)) && (GOAL_TYPES.key? (goal_type_to_track))
|
577
|
-
# log invalid params
|
578
|
-
@logger.log(
|
579
|
-
LogLevelEnum::ERROR,
|
580
|
-
'API_BAD_PARAMETERS',
|
581
|
-
{
|
582
|
-
'{file}' => FILE,
|
583
|
-
'{api}' => ApiMethods::TRACK
|
584
|
-
}
|
585
|
-
)
|
586
|
-
return false
|
587
|
-
end
|
571
|
+
return false unless valid_track_api_params?(user_id, campaign_key, custom_variables, variation_targeting_variables, goal_type_to_track, goal_identifier)
|
588
572
|
|
589
573
|
# Get campaigns settings
|
590
574
|
campaigns = get_campaigns(@settings_file, campaign_key, goal_identifier, goal_type_to_track)
|
591
575
|
|
592
576
|
# Validate campaign
|
593
|
-
if campaigns.nil?
|
594
|
-
return nil
|
595
|
-
end
|
577
|
+
return nil if campaigns.nil?
|
596
578
|
|
597
579
|
metric_map = {}
|
598
580
|
revenue_props = []
|
599
581
|
result = {}
|
600
|
-
batch_event_data = {
|
582
|
+
batch_event_data = { 'ev' => [] }
|
601
583
|
campaigns.each do |campaign|
|
602
584
|
begin
|
603
585
|
campaign_type = campaign['type']
|
586
|
+
result[campaign['key']] = false
|
604
587
|
|
605
|
-
|
606
|
-
@logger.log(
|
607
|
-
LogLevelEnum::ERROR,
|
608
|
-
'API_NOT_APPLICABLE',
|
609
|
-
{
|
610
|
-
'{file}' => FILE,
|
611
|
-
'{api}' => ApiMethods::TRACK,
|
612
|
-
'{userId}' => user_id,
|
613
|
-
'{campaignKey}' => campaign_key,
|
614
|
-
'{campaignType}' => campaign_type,
|
615
|
-
}
|
616
|
-
)
|
617
|
-
result[campaign['key']] = false
|
618
|
-
next
|
619
|
-
end
|
588
|
+
next unless valid_campaign_for_track_api?(user_id, campaign_key, campaign_type)
|
620
589
|
|
621
590
|
variation = @variation_decider.get_variation(user_id, campaign, ApiMethods::TRACK, campaign['key'], custom_variables, variation_targeting_variables, goal_identifier)
|
622
591
|
|
623
592
|
if variation
|
624
593
|
goal = get_campaign_goal(campaign, goal_identifier)
|
625
|
-
|
626
|
-
@logger.log(
|
627
|
-
LogLevelEnum::ERROR,
|
628
|
-
'TRACK_API_GOAL_NOT_FOUND',
|
629
|
-
{
|
630
|
-
'{file}' => FILE,
|
631
|
-
'{goalIdentifier}' => goal_identifier,
|
632
|
-
'{userId}' => user_id,
|
633
|
-
'{campaignKey}' => campaign['key']
|
634
|
-
}
|
635
|
-
)
|
636
|
-
result[campaign['key']] = false
|
637
|
-
next
|
638
|
-
elsif goal['type'] == GoalTypes::REVENUE && !valid_value?(revenue_value)
|
639
|
-
@logger.log(
|
640
|
-
LogLevelEnum::ERROR,
|
641
|
-
'TRACK_API_REVENUE_NOT_PASSED_FOR_REVENUE_GOAL',
|
642
|
-
{
|
643
|
-
'{file}' => FILE,
|
644
|
-
'{userId}' => user_id,
|
645
|
-
'{goalIdentifier}' => goal_identifier,
|
646
|
-
'{campaignKey}' => campaign['key']
|
647
|
-
}
|
648
|
-
)
|
649
|
-
result[campaign['key']] = false
|
650
|
-
next
|
651
|
-
elsif goal['type'] == GoalTypes::CUSTOM
|
652
|
-
revenue_value = nil
|
653
|
-
end
|
594
|
+
next unless valid_goal?(goal, campaign, user_id, goal_identifier, revenue_value)
|
654
595
|
|
655
|
-
if
|
656
|
-
|
657
|
-
else
|
658
|
-
variation['goal_identifier'] = ''
|
659
|
-
identifiers = []
|
660
|
-
end
|
596
|
+
revenue_value = nil if goal['type'] == GoalTypes::CUSTOM
|
597
|
+
identifiers = get_variation_identifiers(variation)
|
661
598
|
|
662
|
-
if
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
# set variation at user storage
|
667
|
-
else
|
668
|
-
@logger.log(
|
669
|
-
LogLevelEnum::INFO,
|
670
|
-
'CAMPAIGN_GOAL_ALREADY_TRACKED',
|
671
|
-
{
|
672
|
-
'{file}' => FILE,
|
673
|
-
'{userId}' => user_id,
|
674
|
-
'{campaignKey}' => campaign['key'],
|
675
|
-
'{goalIdentifier}' => goal_identifier
|
676
|
-
}
|
677
|
-
)
|
678
|
-
result[campaign['key']] = false
|
679
|
-
next
|
680
|
-
end
|
599
|
+
next if campaign_goal_already_tracked?(user_id, campaign, identifiers, goal_identifier)
|
600
|
+
|
601
|
+
@variation_decider.update_goal_identifier(user_id, campaign, variation, goal_identifier)
|
602
|
+
# set variation at user storage
|
681
603
|
|
682
604
|
if defined?(@batch_events)
|
683
|
-
impression = create_bulk_event_impression(
|
684
|
-
@settings_file,
|
685
|
-
campaign['id'],
|
686
|
-
variation['id'],
|
687
|
-
user_id,
|
688
|
-
goal['id'],
|
689
|
-
revenue_value
|
690
|
-
)
|
605
|
+
impression = create_bulk_event_impression(@settings_file, campaign['id'], variation['id'], user_id, goal['id'], revenue_value)
|
691
606
|
@batch_events_queue.enqueue(impression)
|
692
|
-
elsif
|
607
|
+
elsif event_arch_enabled?
|
693
608
|
metric_map[campaign['id']] = goal['id']
|
694
|
-
if goal['type'] == GoalTypes::REVENUE && !(revenue_props.include? goal['revenueProp'])
|
695
|
-
revenue_props << goal['revenueProp']
|
696
|
-
end
|
609
|
+
revenue_props << goal['revenueProp'] if goal['type'] == GoalTypes::REVENUE && !(revenue_props.include? goal['revenueProp'])
|
697
610
|
elsif campaigns.count == 1
|
698
|
-
impression = create_impression(
|
699
|
-
|
700
|
-
|
701
|
-
variation['id'],
|
702
|
-
user_id,
|
703
|
-
@sdk_key,
|
704
|
-
goal['id'],
|
705
|
-
revenue_value
|
706
|
-
)
|
707
|
-
if @event_dispatcher.dispatch(impression)
|
708
|
-
@logger.log(
|
709
|
-
LogLevelEnum::INFO,
|
710
|
-
'IMPRESSION_SUCCESS',
|
711
|
-
{
|
712
|
-
'{file}' => FILE,
|
713
|
-
'{mainKeys}' => JSON.generate({'campaignId' => campaign['id'], 'variationId' => variation['id'], 'goalId' => goal['id']}),
|
714
|
-
'{accountId}' => @account_id,
|
715
|
-
'{endPoint}' => EVENTS::TRACK_GOAL
|
716
|
-
}
|
717
|
-
)
|
718
|
-
end
|
611
|
+
impression = create_impression(@settings_file, campaign['id'], variation['id'], user_id, @sdk_key, goal['id'], revenue_value)
|
612
|
+
main_keys = { 'campaignId' => campaign['id'], 'variationId' => variation['id'], 'goalId' => goal['id'] }
|
613
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_GOAL)
|
719
614
|
else
|
720
|
-
batch_event_data[
|
721
|
-
@settings_file,
|
722
|
-
campaign['id'],
|
723
|
-
variation['id'],
|
724
|
-
user_id,
|
725
|
-
goal['id'],
|
726
|
-
revenue_value
|
727
|
-
)
|
615
|
+
batch_event_data['ev'] << create_bulk_event_impression(@settings_file, campaign['id'], variation['id'], user_id, goal['id'], revenue_value)
|
728
616
|
end
|
729
617
|
result[campaign['key']] = true
|
730
618
|
next
|
731
619
|
end
|
732
|
-
result[campaign['key']] = false
|
733
620
|
rescue StandardError => e
|
734
621
|
@logger.log(
|
735
622
|
LogLevelEnum::ERROR,
|
736
|
-
|
623
|
+
"({file}): {api} API error: #{e.message}",
|
737
624
|
{
|
738
625
|
'{file}' => FILE,
|
739
626
|
'{api}' => ApiMethods::TRACK
|
@@ -742,26 +629,23 @@ class VWO
|
|
742
629
|
end
|
743
630
|
end
|
744
631
|
|
745
|
-
|
746
|
-
if is_event_arch_enabled
|
632
|
+
if event_arch_enabled?
|
747
633
|
properties = get_events_base_properties(@settings_file, goal_identifier)
|
748
634
|
payload = get_track_goal_payload_data(@settings_file, user_id, goal_identifier, revenue_value, metric_map, revenue_props)
|
749
635
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
750
|
-
elsif batch_event_data[
|
636
|
+
elsif batch_event_data['ev'].count != 0
|
751
637
|
paramters = get_batch_event_query_params(@settings_file['accountId'], @sdk_key, @usage_stats.usage_stats)
|
752
638
|
batch_events_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
753
|
-
|
639
|
+
return nil unless batch_events_dispatcher.dispatch(batch_event_data, nil, paramters)
|
754
640
|
end
|
755
641
|
|
756
|
-
if result.length
|
757
|
-
return nil
|
758
|
-
end
|
642
|
+
return nil if result.length == 0
|
759
643
|
|
760
644
|
result
|
761
645
|
rescue StandardError => e
|
762
646
|
@logger.log(
|
763
647
|
LogLevelEnum::ERROR,
|
764
|
-
|
648
|
+
"({file}): {api} API error: #{e.message}",
|
765
649
|
{
|
766
650
|
'{file}' => FILE,
|
767
651
|
'{api}' => ApiMethods::TRACK
|
@@ -769,7 +653,6 @@ class VWO
|
|
769
653
|
)
|
770
654
|
false
|
771
655
|
end
|
772
|
-
|
773
656
|
# This API method: Identifies whether the user becomes a part of feature rollout/test or not.
|
774
657
|
# 1. Validates the arguments being passed
|
775
658
|
# 2. Checks if user is eligible to get bucketed into the feature test/rollout,
|
@@ -785,9 +668,7 @@ class VWO
|
|
785
668
|
|
786
669
|
def feature_enabled?(campaign_key, user_id, options = {})
|
787
670
|
@logger.set_api_name(ApiMethods::IS_FEATURE_ENABLED)
|
788
|
-
if
|
789
|
-
return false
|
790
|
-
end
|
671
|
+
return false if opted_out?(ApiMethods::IS_FEATURE_ENABLED)
|
791
672
|
|
792
673
|
unless @is_instance_valid
|
793
674
|
@logger.log(
|
@@ -808,7 +689,7 @@ class VWO
|
|
808
689
|
|
809
690
|
# Validate input parameters
|
810
691
|
unless valid_string?(campaign_key) && valid_string?(user_id) && (custom_variables.nil? || valid_hash?(custom_variables)) &&
|
811
|
-
|
692
|
+
(variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
812
693
|
@logger.log(
|
813
694
|
LogLevelEnum::ERROR,
|
814
695
|
'API_BAD_PARAMETERS',
|
@@ -850,7 +731,7 @@ class VWO
|
|
850
731
|
'{api}' => ApiMethods::IS_FEATURE_ENABLED,
|
851
732
|
'{userId}' => user_id,
|
852
733
|
'{campaignKey}' => campaign_key,
|
853
|
-
'{campaignType}' => campaign_type
|
734
|
+
'{campaignType}' => campaign_type
|
854
735
|
}
|
855
736
|
)
|
856
737
|
return false
|
@@ -864,7 +745,7 @@ class VWO
|
|
864
745
|
|
865
746
|
# if campaign type is feature_test Send track call to server
|
866
747
|
|
867
|
-
if
|
748
|
+
if eligible_to_send_impression?
|
868
749
|
if defined?(@batch_events)
|
869
750
|
impression = create_bulk_event_impression(
|
870
751
|
@settings_file,
|
@@ -873,7 +754,7 @@ class VWO
|
|
873
754
|
user_id
|
874
755
|
)
|
875
756
|
@batch_events_queue.enqueue(impression)
|
876
|
-
elsif
|
757
|
+
elsif event_arch_enabled?
|
877
758
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_VARIATION_SHOWN, @usage_stats.usage_stats)
|
878
759
|
payload = get_track_user_payload_data(@settings_file, user_id, EventEnum::VWO_VARIATION_SHOWN, campaign['id'], variation['id'])
|
879
760
|
@event_dispatcher.dispatch_event_arch_post(properties, payload)
|
@@ -889,17 +770,8 @@ class VWO
|
|
889
770
|
usage_stats: @usage_stats.usage_stats
|
890
771
|
)
|
891
772
|
|
892
|
-
|
893
|
-
@
|
894
|
-
LogLevelEnum::INFO,
|
895
|
-
'IMPRESSION_SUCCESS',
|
896
|
-
{
|
897
|
-
'{file}' => FILE,
|
898
|
-
'{mainKeys}' => JSON.generate({'campaignId' => impression[:experiment_id]}),
|
899
|
-
'{accountId}' => @account_id,
|
900
|
-
'{endPoint}' => EVENTS::TRACK_USER
|
901
|
-
}
|
902
|
-
)
|
773
|
+
main_keys = { 'campaignId' => impression[:experiment_id] }
|
774
|
+
@event_dispatcher.dispatch(impression, main_keys, EVENTS::TRACK_USER)
|
903
775
|
end
|
904
776
|
|
905
777
|
else
|
@@ -914,11 +786,11 @@ class VWO
|
|
914
786
|
}
|
915
787
|
)
|
916
788
|
end
|
917
|
-
if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
789
|
+
result = if campaign_type == CampaignTypes::FEATURE_ROLLOUT
|
790
|
+
true
|
791
|
+
else
|
792
|
+
variation['isFeatureEnabled']
|
793
|
+
end
|
922
794
|
|
923
795
|
if result
|
924
796
|
@logger.log(
|
@@ -948,7 +820,7 @@ class VWO
|
|
948
820
|
rescue StandardError => e
|
949
821
|
@logger.log(
|
950
822
|
LogLevelEnum::ERROR,
|
951
|
-
|
823
|
+
"({file}): {api} API error: #{e.message}",
|
952
824
|
{
|
953
825
|
'{file}' => FILE,
|
954
826
|
'{api}' => ApiMethods::IS_FEATURE_ENABLED
|
@@ -978,9 +850,7 @@ class VWO
|
|
978
850
|
|
979
851
|
def get_feature_variable_value(campaign_key, variable_key, user_id, options = {})
|
980
852
|
@logger.set_api_name(ApiMethods::GET_FEATURE_VARIABLE_VALUE)
|
981
|
-
if
|
982
|
-
return nil
|
983
|
-
end
|
853
|
+
return nil if opted_out?(ApiMethods::GET_FEATURE_VARIABLE_VALUE)
|
984
854
|
|
985
855
|
unless @is_instance_valid
|
986
856
|
@logger.log(
|
@@ -1000,7 +870,7 @@ class VWO
|
|
1000
870
|
variation_targeting_variables = options[:variation_targeting_variables]
|
1001
871
|
|
1002
872
|
unless valid_string?(campaign_key) && valid_string?(variable_key) && valid_string?(user_id) &&
|
1003
|
-
|
873
|
+
(custom_variables.nil? || valid_hash?(custom_variables)) && (variation_targeting_variables.nil? || valid_hash?(variation_targeting_variables))
|
1004
874
|
@logger.log(
|
1005
875
|
LogLevelEnum::ERROR,
|
1006
876
|
'API_BAD_PARAMETERS',
|
@@ -1041,7 +911,7 @@ class VWO
|
|
1041
911
|
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE,
|
1042
912
|
'{userId}' => user_id,
|
1043
913
|
'{campaignKey}' => campaign_key,
|
1044
|
-
'{campaignType}' => campaign_type
|
914
|
+
'{campaignType}' => campaign_type
|
1045
915
|
}
|
1046
916
|
)
|
1047
917
|
return
|
@@ -1052,32 +922,33 @@ class VWO
|
|
1052
922
|
# Check if variation has been assigned to user
|
1053
923
|
return unless variation
|
1054
924
|
|
1055
|
-
|
925
|
+
case campaign_type
|
926
|
+
when CampaignTypes::FEATURE_ROLLOUT
|
1056
927
|
variables = campaign['variables']
|
1057
|
-
|
928
|
+
when CampaignTypes::FEATURE_TEST
|
1058
929
|
if !variation['isFeatureEnabled']
|
1059
930
|
@logger.log(
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
931
|
+
LogLevelEnum::INFO,
|
932
|
+
'FEATURE_STATUS',
|
933
|
+
{
|
934
|
+
'{file}' => FILE,
|
935
|
+
'{userId}' => user_id,
|
936
|
+
'{campaignKey}' => campaign_key,
|
937
|
+
'{status}' => 'disabled'
|
938
|
+
}
|
939
|
+
)
|
1069
940
|
variation = get_control_variation(campaign)
|
1070
941
|
else
|
1071
942
|
@logger.log(
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
943
|
+
LogLevelEnum::INFO,
|
944
|
+
'FEATURE_STATUS',
|
945
|
+
{
|
946
|
+
'{file}' => FILE,
|
947
|
+
'{userId}' => user_id,
|
948
|
+
'{campaignKey}' => campaign_key,
|
949
|
+
'{status}' => 'enabled'
|
950
|
+
}
|
951
|
+
)
|
1081
952
|
end
|
1082
953
|
variables = variation['variables']
|
1083
954
|
end
|
@@ -1105,14 +976,14 @@ class VWO
|
|
1105
976
|
'{variableKey}' => variable_key,
|
1106
977
|
'{variableValue}' => variable['value'],
|
1107
978
|
'{campaignKey}' => campaign_key,
|
1108
|
-
'{userId}' => user_id
|
979
|
+
'{userId}' => user_id
|
1109
980
|
}
|
1110
981
|
)
|
1111
982
|
get_type_casted_feature_value(variable['value'], variable['type'])
|
1112
983
|
rescue StandardError => e
|
1113
984
|
@logger.log(
|
1114
985
|
LogLevelEnum::ERROR,
|
1115
|
-
|
986
|
+
"({file}): {api} API error: #{e.message}",
|
1116
987
|
{
|
1117
988
|
'{file}' => FILE,
|
1118
989
|
'{api}' => ApiMethods::GET_FEATURE_VARIABLE_VALUE
|
@@ -1131,9 +1002,7 @@ class VWO
|
|
1131
1002
|
|
1132
1003
|
def push(tag_key, tag_value, user_id = nil)
|
1133
1004
|
@logger.set_api_name(ApiMethods::PUSH)
|
1134
|
-
if
|
1135
|
-
return {}
|
1136
|
-
end
|
1005
|
+
return {} if opted_out?(ApiMethods::PUSH)
|
1137
1006
|
|
1138
1007
|
unless @is_instance_valid
|
1139
1008
|
@logger.log(
|
@@ -1169,42 +1038,42 @@ class VWO
|
|
1169
1038
|
end
|
1170
1039
|
|
1171
1040
|
result = {}
|
1172
|
-
custom_dimension_map.each do |
|
1173
|
-
if !
|
1174
|
-
custom_dimension_map.delete(
|
1175
|
-
result[
|
1041
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1042
|
+
if !tagkey.is_a?(Symbol) || !tagvalue.is_a?(String)
|
1043
|
+
custom_dimension_map.delete(tagkey)
|
1044
|
+
result[tagkey] = false
|
1176
1045
|
next
|
1177
1046
|
end
|
1178
1047
|
|
1179
|
-
if
|
1048
|
+
if tagkey.length > PushApi::TAG_KEY_LENGTH || tagkey.length == 0
|
1180
1049
|
@logger.log(
|
1181
1050
|
LogLevelEnum::ERROR,
|
1182
1051
|
'TAG_KEY_LENGTH_EXCEEDED',
|
1183
1052
|
{
|
1184
1053
|
'{file}' => FILE,
|
1185
1054
|
'{userId}' => user_id,
|
1186
|
-
'{tagKey}' =>
|
1055
|
+
'{tagKey}' => tagkey
|
1187
1056
|
}
|
1188
1057
|
)
|
1189
|
-
custom_dimension_map.delete(
|
1190
|
-
result[
|
1058
|
+
custom_dimension_map.delete(tagkey)
|
1059
|
+
result[tagkey] = false
|
1191
1060
|
next
|
1192
1061
|
end
|
1193
1062
|
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
}
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1063
|
+
next unless tagvalue.length > PushApi::TAG_VALUE_LENGTH || tagvalue.length == 0
|
1064
|
+
|
1065
|
+
@logger.log(
|
1066
|
+
LogLevelEnum::ERROR,
|
1067
|
+
'TAG_VALUE_LENGTH_EXCEEDED',
|
1068
|
+
{
|
1069
|
+
'{file}' => FILE,
|
1070
|
+
'{userId}' => user_id,
|
1071
|
+
'{tagKey}' => tagkey,
|
1072
|
+
'{tagValue}' => tagvalue
|
1073
|
+
}
|
1074
|
+
)
|
1075
|
+
custom_dimension_map.delete(tagkey)
|
1076
|
+
result[tagkey] = false
|
1208
1077
|
end
|
1209
1078
|
|
1210
1079
|
if custom_dimension_map.count == 0
|
@@ -1220,62 +1089,51 @@ class VWO
|
|
1220
1089
|
end
|
1221
1090
|
|
1222
1091
|
if defined?(@batch_events)
|
1223
|
-
custom_dimension_map.each do |
|
1224
|
-
impression = get_batch_event_url_params(@settings_file,
|
1092
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1093
|
+
impression = get_batch_event_url_params(@settings_file, tagkey, tagvalue, user_id)
|
1225
1094
|
@batch_events_queue.enqueue(impression)
|
1226
1095
|
end
|
1227
1096
|
resp = true
|
1228
|
-
elsif
|
1097
|
+
elsif event_arch_enabled?
|
1229
1098
|
properties = get_events_base_properties(@settings_file, EventEnum::VWO_SYNC_VISITOR_PROP)
|
1230
1099
|
payload = get_push_payload_data(@settings_file, user_id, EventEnum::VWO_SYNC_VISITOR_PROP, custom_dimension_map)
|
1231
1100
|
resp = @event_dispatcher.dispatch_event_arch_post(properties, payload)
|
1232
1101
|
elsif custom_dimension_map.count == 1
|
1233
|
-
custom_dimension_map.each do |
|
1234
|
-
impression = get_url_params(@settings_file,
|
1235
|
-
|
1236
|
-
@
|
1237
|
-
LogLevelEnum::INFO,
|
1238
|
-
'IMPRESSION_SUCCESS',
|
1239
|
-
{
|
1240
|
-
'{file}' => FILE,
|
1241
|
-
'{endPoint}' => ApiMethods::PUSH,
|
1242
|
-
'{accountId}' => @settings_file['accountId'],
|
1243
|
-
'{mainKeys}' => JSON.generate({'tags' => impression['tags']}),
|
1244
|
-
}
|
1245
|
-
)
|
1102
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1103
|
+
impression = get_url_params(@settings_file, tagkey, tagvalue, user_id, @sdk_key)
|
1104
|
+
main_keys = { 'tags' => impression['tags'] }
|
1105
|
+
result[tagkey] = @event_dispatcher.dispatch(impression, main_keys, EVENTS::PUSH)
|
1246
1106
|
end
|
1247
1107
|
resp = true
|
1248
1108
|
else
|
1249
|
-
batch_event_data = {
|
1250
|
-
custom_dimension_map.each do |
|
1251
|
-
batch_event_data[
|
1109
|
+
batch_event_data = { 'ev' => [] }
|
1110
|
+
custom_dimension_map.each do |tagkey, tagvalue|
|
1111
|
+
batch_event_data['ev'] << get_batch_event_url_params(@settings_file, tagkey, tagvalue, user_id)
|
1252
1112
|
end
|
1253
1113
|
paramters = get_batch_event_query_params(@settings_file['accountId'], @sdk_key, @usage_stats.usage_stats)
|
1254
1114
|
batch_events_dispatcher = VWO::Services::BatchEventsDispatcher.new(@is_development_mode)
|
1255
1115
|
resp = batch_events_dispatcher.dispatch(batch_event_data, nil, paramters)
|
1256
1116
|
end
|
1257
1117
|
|
1258
|
-
|
1118
|
+
prepare_push_response(custom_dimension_map, resp, result)
|
1259
1119
|
rescue StandardError => e
|
1260
1120
|
@logger.log(
|
1261
1121
|
LogLevelEnum::ERROR,
|
1262
|
-
|
1263
|
-
{'{file}' => FILE}
|
1122
|
+
"({file}): push API error: #{e.message}",
|
1123
|
+
{ '{file}' => FILE }
|
1264
1124
|
)
|
1265
1125
|
false
|
1266
1126
|
end
|
1267
1127
|
|
1268
|
-
def
|
1128
|
+
def eligible_to_send_impression?
|
1269
1129
|
!@user_storage || !@variation_decider.has_stored_variation
|
1270
1130
|
end
|
1271
1131
|
|
1272
1132
|
# Manually flush impression events to VWO which are queued in batch queue as per batchEvents config
|
1273
|
-
# @return[bool]
|
1133
|
+
# @return[bool]
|
1274
1134
|
def flush_events
|
1275
1135
|
@logger.set_api_name(ApiMethods::FLUSH_EVENTS)
|
1276
|
-
if
|
1277
|
-
return false
|
1278
|
-
end
|
1136
|
+
return false if opted_out?(ApiMethods::FLUSH_EVENTS)
|
1279
1137
|
|
1280
1138
|
unless @is_instance_valid
|
1281
1139
|
@logger.log(
|
@@ -1297,7 +1155,7 @@ class VWO
|
|
1297
1155
|
rescue StandardError => e
|
1298
1156
|
@logger.log(
|
1299
1157
|
LogLevelEnum::ERROR,
|
1300
|
-
|
1158
|
+
"({file}): {api} API error: #{e.message}",
|
1301
1159
|
{
|
1302
1160
|
'{file}' => FILE,
|
1303
1161
|
'{api}' => ApiMethods::FLUSH_EVENTS
|
@@ -1309,24 +1167,20 @@ class VWO
|
|
1309
1167
|
def get_goal_type_to_track(options)
|
1310
1168
|
goal_type_to_track = nil
|
1311
1169
|
if !options.key?(:goal_type_to_track)
|
1312
|
-
|
1313
|
-
goal_type_to_track = @goal_type_to_track
|
1314
|
-
else
|
1315
|
-
goal_type_to_track = GOAL_TYPES['ALL']
|
1316
|
-
end
|
1170
|
+
goal_type_to_track = @goal_type_to_track || GOAL_TYPES['ALL']
|
1317
1171
|
elsif GOAL_TYPES.key? options[:goal_type_to_track]
|
1318
1172
|
goal_type_to_track = options[:goal_type_to_track]
|
1319
1173
|
else
|
1320
1174
|
@logger.log(
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1175
|
+
LogLevelEnum::ERROR,
|
1176
|
+
'CONFIG_PARAMETER_INVALID',
|
1177
|
+
{
|
1178
|
+
'{file}' => FILE,
|
1179
|
+
'{parameter}' => 'goal_type_to_track',
|
1180
|
+
'{type}' => 'string(REVENUE, CUSTOM, ALL)',
|
1181
|
+
'{api}' => 'init'
|
1182
|
+
}
|
1183
|
+
)
|
1330
1184
|
end
|
1331
1185
|
goal_type_to_track
|
1332
1186
|
end
|
@@ -1336,38 +1190,37 @@ class VWO
|
|
1336
1190
|
# return[bool]
|
1337
1191
|
#
|
1338
1192
|
def set_opt_out
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1193
|
+
@logger.set_api_name(ApiMethods::OPT_OUT)
|
1194
|
+
@logger.log(
|
1195
|
+
LogLevelEnum::INFO,
|
1196
|
+
'OPT_OUT_API_CALLED',
|
1197
|
+
{
|
1198
|
+
'{file}' => FILE
|
1199
|
+
}
|
1200
|
+
)
|
1201
|
+
if defined?(@batch_events) && !@batch_events_queue.nil?
|
1202
|
+
@batch_events_queue.flush(manual: true)
|
1203
|
+
@batch_events_queue.kill_thread
|
1204
|
+
end
|
1351
1205
|
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1206
|
+
@is_opted_out = true
|
1207
|
+
@settings_file = nil
|
1208
|
+
@user_storage = nil
|
1209
|
+
@event_dispatcher = nil
|
1210
|
+
@variation_decider = nil
|
1211
|
+
@config = nil
|
1212
|
+
@usage_stats = nil
|
1213
|
+
@batch_event_dispatcher = nil
|
1214
|
+
@batch_events_queue = nil
|
1215
|
+
@batch_events = nil
|
1216
|
+
|
1217
|
+
@is_opted_out
|
1364
1218
|
end
|
1365
1219
|
|
1366
|
-
|
1367
1220
|
# Check if VWO SDK is manually opted out
|
1368
1221
|
# @param[String] :api_name api_name is used in logging
|
1369
1222
|
# @return[bool]
|
1370
|
-
def
|
1223
|
+
def opted_out?(api_name)
|
1371
1224
|
if @is_opted_out
|
1372
1225
|
@logger.log(
|
1373
1226
|
LogLevelEnum::INFO,
|
@@ -1378,10 +1231,10 @@ class VWO
|
|
1378
1231
|
}
|
1379
1232
|
)
|
1380
1233
|
end
|
1381
|
-
|
1234
|
+
@is_opted_out
|
1382
1235
|
end
|
1383
1236
|
|
1384
|
-
def
|
1385
|
-
|
1237
|
+
def event_arch_enabled?
|
1238
|
+
@settings_file.key?('isEventArchEnabled') && @settings_file['isEventArchEnabled']
|
1386
1239
|
end
|
1387
1240
|
end
|