kameleoon-client-ruby 2.1.0 → 2.1.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/kameleoon/client.rb +79 -133
- data/lib/kameleoon/configuration/rule.rb +1 -1
- data/lib/kameleoon/data/browser.rb +33 -0
- data/lib/kameleoon/data/conversion.rb +26 -0
- data/lib/kameleoon/data/custom_data.rb +53 -0
- data/lib/kameleoon/data/data.rb +35 -0
- data/lib/kameleoon/data/device.rb +26 -0
- data/lib/kameleoon/data/page_view.rb +31 -0
- data/lib/kameleoon/data/user_agent.rb +14 -0
- data/lib/kameleoon/network/activity_event.rb +31 -0
- data/lib/kameleoon/network/experiment_event.rb +35 -0
- data/lib/kameleoon/network/uri_helper.rb +36 -0
- data/lib/kameleoon/network/url_provider.rb +71 -0
- data/lib/kameleoon/request.rb +5 -19
- data/lib/kameleoon/targeting/condition.rb +40 -11
- data/lib/kameleoon/targeting/condition_factory.rb +35 -12
- data/lib/kameleoon/targeting/conditions/browser_condition.rb +71 -0
- data/lib/kameleoon/targeting/conditions/conversion_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/custom_datum.rb +60 -65
- data/lib/kameleoon/targeting/conditions/device_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -12
- data/lib/kameleoon/targeting/conditions/page_title_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/page_url_condition.rb +21 -0
- data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +65 -0
- data/lib/kameleoon/targeting/conditions/string_value_condition.rb +40 -0
- data/lib/kameleoon/targeting/conditions/target_experiment.rb +4 -8
- data/lib/kameleoon/targeting/conditions/unknown_condition.rb +15 -0
- data/lib/kameleoon/targeting/conditions/visitor_code_condition.rb +16 -0
- data/lib/kameleoon/targeting/models.rb +0 -24
- data/lib/kameleoon/utils.rb +1 -1
- data/lib/kameleoon/version.rb +28 -1
- metadata +22 -3
- data/lib/kameleoon/data.rb +0 -175
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1aef3f7b97d4a32024bec989ed4356cc1d10425c16b419b55f524cf1abfd4f52
|
4
|
+
data.tar.gz: 5705b067a3effc12b7f38ccef23e01ee28e370b99a212fd371ce0c863184c3ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99cc273ca6010c9ce2c451e7a7cb3795e4b264b670fb8009436e5b9ddbaacf388e894f0922926bf92113ebf9f211636f4b4fc2a34fc01babcf848327bba798f8
|
7
|
+
data.tar.gz: 3686a34890b5438e5d0ca878cbb0bfb89386f2150267c73ef27754d207c6f918aad3355a312045251d3dea15fc2faa6558433f172b907ae4e913c7b60cc204f4
|
data/lib/kameleoon/client.rb
CHANGED
@@ -4,9 +4,13 @@ require 'kameleoon/targeting/models'
|
|
4
4
|
require 'kameleoon/request'
|
5
5
|
require 'kameleoon/exceptions'
|
6
6
|
require 'kameleoon/cookie'
|
7
|
+
require 'kameleoon/data/user_agent'
|
7
8
|
require 'kameleoon/configuration/feature_flag'
|
8
9
|
require 'kameleoon/configuration/variation'
|
9
10
|
require 'kameleoon/configuration/settings'
|
11
|
+
require 'kameleoon/network/activity_event'
|
12
|
+
require 'kameleoon/network/experiment_event'
|
13
|
+
require 'kameleoon/network/url_provider'
|
10
14
|
require 'kameleoon/real_time/real_time_configuration_service'
|
11
15
|
require 'kameleoon/storage/variation_storage'
|
12
16
|
require 'kameleoon/hybrid/manager'
|
@@ -39,9 +43,8 @@ module Kameleoon
|
|
39
43
|
@default_timeout = config['default_timeout'] || default_timeout # in ms
|
40
44
|
refresh_interval = config['actions_configuration_refresh_interval']
|
41
45
|
@interval = refresh_interval.nil? ? interval : "#{refresh_interval}m"
|
42
|
-
|
43
|
-
@
|
44
|
-
@events_url = 'https://events.kameleoon.com:8110/'
|
46
|
+
data_api_url = config['tracking_url'] || Network::UrlProvider::DEFAULT_DATA_API_URL
|
47
|
+
@url_provider = Network::UrlProvider.new(@site_code, data_api_url)
|
45
48
|
@real_time_configuration_service = nil
|
46
49
|
@update_configuration_handler = nil
|
47
50
|
@fetch_configuration_update_job = nil
|
@@ -129,22 +132,22 @@ module Kameleoon
|
|
129
132
|
"Experiment #{experiment_id} is not found"
|
130
133
|
end
|
131
134
|
check_site_code_enable(experiment)
|
132
|
-
|
135
|
+
targeted = check_targeting(visitor_code, experiment_id, experiment)
|
136
|
+
if targeted
|
133
137
|
# saved_variation = get_valid_saved_variation(visitor_code, experiment)
|
134
138
|
variation_id = calculate_variation_for_experiment(visitor_code, experiment)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
else
|
140
|
-
track_experiment(visitor_code, experiment_id, REFERENCE, true)
|
141
|
-
raise Exception::NotAllocated.new(visitor_code),
|
142
|
-
"Experiment #{experiment_id} is not active for visitor #{visitor_code}"
|
143
|
-
end
|
144
|
-
else
|
139
|
+
save_variation(visitor_code, experiment_id, variation_id)
|
140
|
+
end
|
141
|
+
_send_tracking_request(visitor_code, experiment_id, variation_id)
|
142
|
+
unless targeted
|
145
143
|
raise Exception::NotTargeted.new(visitor_code),
|
146
144
|
"Experiment #{experiment_id} is not targeted for visitor #{visitor_code}"
|
147
145
|
end
|
146
|
+
if variation_id.nil?
|
147
|
+
raise Exception::NotAllocated.new(visitor_code),
|
148
|
+
"Experiment #{experiment_id} is not active for visitor #{visitor_code}"
|
149
|
+
end
|
150
|
+
variation_id
|
148
151
|
end
|
149
152
|
|
150
153
|
##
|
@@ -208,7 +211,7 @@ module Kameleoon
|
|
208
211
|
def flush(visitor_code = nil)
|
209
212
|
check_visitor_code(visitor_code) unless visitor_code.nil?
|
210
213
|
if !visitor_code.nil?
|
211
|
-
|
214
|
+
_send_tracking_request(visitor_code)
|
212
215
|
else
|
213
216
|
@data.select { |_, values| values.any? { |data| !data.sent } }.each_key { |key| flush(key) }
|
214
217
|
end
|
@@ -384,7 +387,7 @@ module Kameleoon
|
|
384
387
|
end
|
385
388
|
|
386
389
|
##
|
387
|
-
# The
|
390
|
+
# The get_remote_data method allows you to retrieve data (according to a key passed as argument)
|
388
391
|
# stored on a remote Kameleoon server. Usually data will be stored on our remote
|
389
392
|
# servers via the use of our Data API.
|
390
393
|
# This method, along with the availability of our highly scalable servers for this purpose, provides a convenient
|
@@ -395,11 +398,11 @@ module Kameleoon
|
|
395
398
|
# This field is optional.
|
396
399
|
#
|
397
400
|
# @return [Hash] Hash object of the json object.
|
398
|
-
def
|
401
|
+
def get_remote_data(key, timeout = @default_timeout)
|
399
402
|
connexion_options = { connect_timeout: (timeout.to_f / 1000.0) }
|
400
|
-
|
403
|
+
url = @url_provider.make_api_data_get_request_url(key)
|
401
404
|
log "Retrieve API Data connexion: #{connexion_options.inspect}"
|
402
|
-
response = get_sync(
|
405
|
+
response = get_sync(url, connexion_options)
|
403
406
|
return nil unless successful_sync?(response)
|
404
407
|
|
405
408
|
JSON.parse(response.body) unless response.nil?
|
@@ -409,7 +412,7 @@ module Kameleoon
|
|
409
412
|
# DEPRECATED. Please use `get_feature_variable` instead.
|
410
413
|
def retrieve_data_from_remote_source(key, timeout = @default_timeout)
|
411
414
|
warn '[DEPRECATION] `retrieve_data_from_remote_source` is deprecated. Please use `get_remote_date` instead.'
|
412
|
-
|
415
|
+
get_remote_data(key, timeout)
|
413
416
|
end
|
414
417
|
|
415
418
|
##
|
@@ -490,7 +493,6 @@ module Kameleoon
|
|
490
493
|
|
491
494
|
private
|
492
495
|
|
493
|
-
API_SSX_URL = 'https://api-ssx.kameleoon.com'
|
494
496
|
REFERENCE = 0
|
495
497
|
DEFAULT_ENVIRONMENT = 'production'
|
496
498
|
CACHE_EXPIRATION_TIMEOUT = 5
|
@@ -507,7 +509,7 @@ module Kameleoon
|
|
507
509
|
def fetch_configuration_job(time_stamp = nil)
|
508
510
|
EM.synchrony do
|
509
511
|
begin
|
510
|
-
ok = obtain_configuration(@
|
512
|
+
ok = obtain_configuration(@environment, time_stamp)
|
511
513
|
if !ok && @settings.real_time_update
|
512
514
|
@settings.real_time_update = false
|
513
515
|
log('Switching to polling mode due to failed fetch')
|
@@ -540,10 +542,10 @@ module Kameleoon
|
|
540
542
|
def start_real_time_configuration_service_if_needed
|
541
543
|
return unless @real_time_configuration_service.nil?
|
542
544
|
|
543
|
-
|
545
|
+
url = @url_provider.make_real_time_url
|
544
546
|
fetch_func = proc { |real_time_event| fetch_configuration_job(real_time_event.time_stamp) }
|
545
547
|
@real_time_configuration_service =
|
546
|
-
Kameleoon::RealTime::RealTimeConfigurationService.new(
|
548
|
+
Kameleoon::RealTime::RealTimeConfigurationService.new(url, fetch_func, method(:log))
|
547
549
|
end
|
548
550
|
|
549
551
|
def stop_real_time_configuration_service_if_needed
|
@@ -577,12 +579,10 @@ module Kameleoon
|
|
577
579
|
# { 'field' => field, 'operator' => operator, 'parameters' => parameters }
|
578
580
|
# end
|
579
581
|
|
580
|
-
def obtain_configuration(
|
582
|
+
def obtain_configuration(environment = @environment, time_stamp = nil)
|
581
583
|
log 'Fetching configuration from Client-Config service'
|
582
|
-
|
583
|
-
|
584
|
-
request_path += "&ts=#{time_stamp}" unless time_stamp.nil?
|
585
|
-
request = request_configuration(request_path)
|
584
|
+
url = @url_provider.make_configuration_url(environment, time_stamp)
|
585
|
+
request = request_configuration(url)
|
586
586
|
return false unless request
|
587
587
|
|
588
588
|
configuration = JSON.parse(request.response)
|
@@ -616,8 +616,8 @@ module Kameleoon
|
|
616
616
|
nil
|
617
617
|
end
|
618
618
|
|
619
|
-
def request_configuration(
|
620
|
-
request = EM::Synchrony.sync get({
|
619
|
+
def request_configuration(url)
|
620
|
+
request = EM::Synchrony.sync get({}, url)
|
621
621
|
unless successful?(request)
|
622
622
|
log "Failed to fetch #{request.inspect}"
|
623
623
|
return false
|
@@ -625,37 +625,6 @@ module Kameleoon
|
|
625
625
|
request
|
626
626
|
end
|
627
627
|
|
628
|
-
def get_common_ssx_parameters(visitor_code)
|
629
|
-
{
|
630
|
-
nonce: Kameleoon::Utils.generate_random_string(16),
|
631
|
-
siteCode: @site_code,
|
632
|
-
visitorCode: visitor_code
|
633
|
-
}
|
634
|
-
end
|
635
|
-
|
636
|
-
def get_experiment_register_url(visitor_code, experiment_id, variation_id = nil, none_variation = false)
|
637
|
-
url = "/experimentTracking?#{URI.encode_www_form(get_common_ssx_parameters(visitor_code))}"
|
638
|
-
url += "&experimentId=#{experiment_id}"
|
639
|
-
return url if variation_id.nil?
|
640
|
-
|
641
|
-
url += "&variationId=#{variation_id}"
|
642
|
-
url += '&noneVariation=true' if none_variation
|
643
|
-
|
644
|
-
url
|
645
|
-
end
|
646
|
-
|
647
|
-
def get_data_register_url(visitor_code)
|
648
|
-
"/dataTracking?#{URI.encode_www_form(get_common_ssx_parameters(visitor_code))}"
|
649
|
-
end
|
650
|
-
|
651
|
-
def get_api_data_request_url(key)
|
652
|
-
mapKey = {
|
653
|
-
siteCode: site_code,
|
654
|
-
key: key
|
655
|
-
}
|
656
|
-
"/data?#{URI.encode_www_form(mapKey)}"
|
657
|
-
end
|
658
|
-
|
659
628
|
def find_feature_flag(feature_key)
|
660
629
|
if feature_key.is_a?(String)
|
661
630
|
feature_flag = @feature_flags.select { |ff| ff.feature_key == feature_key }.first
|
@@ -669,67 +638,6 @@ module Kameleoon
|
|
669
638
|
feature_flag
|
670
639
|
end
|
671
640
|
|
672
|
-
def track_experiment(visitor_code, experiment_id, variation_id = nil, none_variation: false)
|
673
|
-
data_not_sent = data_not_sent(visitor_code)
|
674
|
-
options = {
|
675
|
-
path: get_experiment_register_url(visitor_code, experiment_id, variation_id, none_variation),
|
676
|
-
body: (data_not_sent.map(&:obtain_full_post_text_line).join("\n") || '').encode('UTF-8'),
|
677
|
-
head: { 'Content-Type': 'text/plain' }
|
678
|
-
}
|
679
|
-
set_user_agent_to_headers(visitor_code, options[:head])
|
680
|
-
trial = 0
|
681
|
-
success = false
|
682
|
-
log "Start post tracking experiment: #{data_not_sent.inspect}"
|
683
|
-
Thread.new do
|
684
|
-
while trial < 10
|
685
|
-
log "Send Experiment Tracking #{options.inspect}"
|
686
|
-
response = post_sync(options, @tracking_url)
|
687
|
-
log "Response #{response.inspect}"
|
688
|
-
if successful_sync?(response)
|
689
|
-
data_not_sent.each { |it| it.sent = true }
|
690
|
-
success = true
|
691
|
-
break
|
692
|
-
end
|
693
|
-
trial += 1
|
694
|
-
end
|
695
|
-
if success
|
696
|
-
log "Post to experiment tracking is done after #{trial + 1} trials"
|
697
|
-
else
|
698
|
-
log "Post to experiment tracking is failed after #{trial} trials"
|
699
|
-
end
|
700
|
-
end
|
701
|
-
end
|
702
|
-
|
703
|
-
def track_data(visitor_code)
|
704
|
-
Thread.new do
|
705
|
-
trials = 0
|
706
|
-
data_not_sent = data_not_sent(visitor_code)
|
707
|
-
log "Start post tracking data: #{data_not_sent.inspect}"
|
708
|
-
while trials < 10 && !data_not_sent.empty?
|
709
|
-
options = {
|
710
|
-
path: get_data_register_url(visitor_code),
|
711
|
-
body: (data_not_sent.map(&:obtain_full_post_text_line).join("\n") || '').encode('UTF-8'),
|
712
|
-
head: { 'Content-Type': 'text/plain' }
|
713
|
-
}
|
714
|
-
set_user_agent_to_headers(visitor_code, options[:head])
|
715
|
-
log "Post tracking data for visitor_code: #{visitor_code} with options: #{options.inspect}"
|
716
|
-
response = post_sync(options, @tracking_url)
|
717
|
-
log "Response #{response.inspect}"
|
718
|
-
if successful_sync?(response)
|
719
|
-
data_not_sent.each { |it| it.sent = true }
|
720
|
-
success = true
|
721
|
-
break
|
722
|
-
end
|
723
|
-
trials += 1
|
724
|
-
end
|
725
|
-
if success
|
726
|
-
log "Post to data tracking is done after #{trials + 1} trials"
|
727
|
-
else
|
728
|
-
log "Post to data tracking is failed after #{trials} trials"
|
729
|
-
end
|
730
|
-
end
|
731
|
-
end
|
732
|
-
|
733
641
|
def check_site_code_enable(campaign)
|
734
642
|
raise Exception::SiteCodeDisabled.new(site_code), site_code unless campaign.site_enabled
|
735
643
|
end
|
@@ -770,8 +678,17 @@ module Kameleoon
|
|
770
678
|
def get_condition_data(type, visitor_code, campaign_id)
|
771
679
|
condition_data = nil
|
772
680
|
case type
|
773
|
-
when Kameleoon::Targeting::ConditionType::CUSTOM_DATUM
|
681
|
+
when Kameleoon::Targeting::ConditionType::CUSTOM_DATUM,
|
682
|
+
Kameleoon::Targeting::ConditionType::PAGE_TITLE,
|
683
|
+
Kameleoon::Targeting::ConditionType::PAGE_URL,
|
684
|
+
Kameleoon::Targeting::ConditionType::DEVICE_TYPE,
|
685
|
+
Kameleoon::Targeting::ConditionType::BROWSER,
|
686
|
+
Kameleoon::Targeting::ConditionType::CONVERSIONS
|
774
687
|
condition_data = (@data[visitor_code] || []).flatten
|
688
|
+
when Kameleoon::Targeting::ConditionType::SDK_LANGUAGE
|
689
|
+
condition_data = Kameleoon::Targeting::SdkInfo.new(Kameleoon::SDK_NAME, Kameleoon::SDK_VERSION)
|
690
|
+
when Kameleoon::Targeting::ConditionType::VISITOR_CODE
|
691
|
+
condition_data = visitor_code
|
775
692
|
when Kameleoon::Targeting::ConditionType::TARGET_EXPERIMENT
|
776
693
|
condition_data = @variation_storage.get_hash_saved_variation_id(visitor_code)
|
777
694
|
when Kameleoon::Targeting::ConditionType::EXCLUSIVE_EXPERIMENT
|
@@ -790,10 +707,11 @@ module Kameleoon
|
|
790
707
|
variation, rule = _calculate_variation_key_for_feature(visitor_code, feature_flag)
|
791
708
|
variation_key = _get_variation_key(variation, rule, feature_flag)
|
792
709
|
unless rule.nil?
|
793
|
-
|
710
|
+
experiment_id = rule.experiment_id
|
794
711
|
variation_id = variation.variation_id unless variation.nil?
|
795
|
-
|
712
|
+
save_variation(visitor_code, experiment_id, variation_id)
|
796
713
|
end
|
714
|
+
_send_tracking_request(visitor_code, experiment_id, variation_id)
|
797
715
|
[feature_flag, variation_key]
|
798
716
|
end
|
799
717
|
|
@@ -809,11 +727,12 @@ module Kameleoon
|
|
809
727
|
hash_rule = obtain_hash_double_rule(visitor_code, rule.id, rule.respool_time)
|
810
728
|
# check main expostion for rule with hashRule
|
811
729
|
if hash_rule <= rule.exposition
|
730
|
+
return [rule.variation_by_exposition[0], rule] if rule.targeted_delivery_type?
|
731
|
+
|
812
732
|
# uses for variation's expositions
|
813
733
|
hash_variation = obtain_hash_double_rule(visitor_code, rule.experiment_id, rule.respool_time)
|
814
734
|
# get variation key with new hashVariation
|
815
735
|
variation = rule.get_variation(hash_variation)
|
816
|
-
# variation_key can be nil for experiment rules only, for targeted rule will be always exist
|
817
736
|
return [variation, rule] unless variation.nil?
|
818
737
|
# if visitor is targeted for targeted rule then break cycle -> return default
|
819
738
|
elsif rule.targeted_delivery_type?
|
@@ -833,19 +752,46 @@ module Kameleoon
|
|
833
752
|
def _get_variation_key(var_by_exp, rule, feature_flag)
|
834
753
|
return var_by_exp.variation_key unless var_by_exp.nil?
|
835
754
|
|
836
|
-
return Kameleoon::Configuration::VariationType::VARIATION_OFF if !rule.nil? && rule.
|
755
|
+
return Kameleoon::Configuration::VariationType::VARIATION_OFF if !rule.nil? && rule.experimentation_type?
|
837
756
|
|
838
757
|
feature_flag.default_variation_key
|
839
758
|
end
|
840
759
|
|
841
760
|
##
|
842
761
|
# helper method for sending tracking requests for new FF
|
843
|
-
def _send_tracking_request(visitor_code, experiment_id, variation_id)
|
844
|
-
|
845
|
-
|
846
|
-
|
762
|
+
def _send_tracking_request(visitor_code, experiment_id = nil, variation_id = nil)
|
763
|
+
data_not_sent = data_not_sent(visitor_code)
|
764
|
+
if experiment_id.nil? || variation_id.nil?
|
765
|
+
data_not_sent.append(Network::ActivityEvent.new) if data_not_sent.empty?
|
847
766
|
else
|
848
|
-
|
767
|
+
data_not_sent.append(Network::ExperimentEvent.new(experiment_id, variation_id))
|
768
|
+
end
|
769
|
+
options = {
|
770
|
+
body: (data_not_sent.map(&:obtain_full_post_text_line).join("\n") || '').encode('UTF-8'),
|
771
|
+
head: { 'Content-Type': 'text/plain' }
|
772
|
+
}
|
773
|
+
set_user_agent_to_headers(visitor_code, options[:head])
|
774
|
+
url = @url_provider.make_tracking_url(visitor_code)
|
775
|
+
trial = 0
|
776
|
+
success = false
|
777
|
+
log "Start post tracking: #{data_not_sent.inspect}"
|
778
|
+
Thread.new do
|
779
|
+
while trial < 10
|
780
|
+
log "Send tracking #{options.inspect}"
|
781
|
+
response = post_sync(options, url)
|
782
|
+
log "Response #{response.inspect}"
|
783
|
+
if successful_sync?(response)
|
784
|
+
data_not_sent.each { |it| it.sent = true }
|
785
|
+
success = true
|
786
|
+
break
|
787
|
+
end
|
788
|
+
trial += 1
|
789
|
+
end
|
790
|
+
if success
|
791
|
+
log "Post to tracking is done after #{trial + 1} trials"
|
792
|
+
else
|
793
|
+
log "Post to tracking is failed after #{trial} trials"
|
794
|
+
end
|
849
795
|
end
|
850
796
|
end
|
851
797
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative 'data'
|
3
|
+
|
4
|
+
module Kameleoon
|
5
|
+
module BrowserType
|
6
|
+
CHROME = 0
|
7
|
+
INTERNET_EXPLORER = 1
|
8
|
+
FIREFOX = 2
|
9
|
+
SAFARI = 3
|
10
|
+
OPERA = 4
|
11
|
+
OTHER = 5
|
12
|
+
end
|
13
|
+
|
14
|
+
# Represents browser data for tracking calls
|
15
|
+
class Browser < Data
|
16
|
+
attr_reader :type, :version
|
17
|
+
|
18
|
+
# @param [BrowserType] browser_type Browser type, can be: CHROME, INTERNET_EXPLORER, FIREFOX, SAFARI, OPERA, OTHER
|
19
|
+
# @param [float] version Version of browser
|
20
|
+
def initialize(browser_type, version = Float::NAN)
|
21
|
+
super(DataType::BROWSER)
|
22
|
+
@type = browser_type
|
23
|
+
@version = version
|
24
|
+
end
|
25
|
+
|
26
|
+
def obtain_full_post_text_line
|
27
|
+
nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
|
28
|
+
url = "eventType=staticData&browserIndex=#{@type}&nonce=#{nonce}"
|
29
|
+
url.concat("&browserVersion=#{@version}") if @version.is_a?(Integer) || (@version.is_a?(Float) && !@version.nan?)
|
30
|
+
url
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'data'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
# Conversion class uses for tracking conversion
|
8
|
+
class Conversion < Data
|
9
|
+
attr_reader :goal_id, :revenue, :negative
|
10
|
+
|
11
|
+
# @param [Integer] goal_id Id of the goal associated to the conversion
|
12
|
+
# @param [Float] revenue Optional field - Revenue associated to the conversion.
|
13
|
+
# @param [Boolean] negative Optional field - If the revenue is negative. By default it's positive.
|
14
|
+
def initialize(goal_id, revenue = 0.0, negative = false)
|
15
|
+
super(DataType::CONVERSION)
|
16
|
+
@goal_id = goal_id
|
17
|
+
@revenue = revenue || 0.0
|
18
|
+
@negative = negative || false
|
19
|
+
end
|
20
|
+
|
21
|
+
def obtain_full_post_text_line
|
22
|
+
nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
|
23
|
+
"eventType=conversion&goalId=#{@goal_id}&revenue=#{@revenue}&negative=#{@negative}&nonce=#{nonce}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'data'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
# Represents any custom data for targeting conditions
|
8
|
+
class CustomData < Data
|
9
|
+
attr_reader :id, :values
|
10
|
+
|
11
|
+
# @param [Integer] id Id of the custom data
|
12
|
+
# @param [String] value Value of the custom data
|
13
|
+
# @param [Array] values Array of values of the custom data
|
14
|
+
#
|
15
|
+
# @overload
|
16
|
+
# @param [Hash] hash Json value encoded in a hash.
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
|
+
def initialize(arg0, *args)
|
19
|
+
super(DataType::CUSTOM)
|
20
|
+
if arg0.is_a?(Hash)
|
21
|
+
hash = arg0
|
22
|
+
id = hash['id']
|
23
|
+
raise Kameleoon::Exception::NotFound.new('id'), '"id" is mandatory' if id.nil?
|
24
|
+
|
25
|
+
@id = id.to_s
|
26
|
+
value = hash['value']
|
27
|
+
values = hash['values']
|
28
|
+
if values.nil? && value.nil?
|
29
|
+
raise Kameleoon::Exception::NotFound.new('value or values'), '"value" or "values" is mandatory'
|
30
|
+
end
|
31
|
+
|
32
|
+
if values.nil?
|
33
|
+
@values = [value]
|
34
|
+
else
|
35
|
+
@values = values.is_a?(Array) ? values.dup : [values]
|
36
|
+
@values.append(value) unless value.nil?
|
37
|
+
end
|
38
|
+
else
|
39
|
+
@id = arg0.to_s
|
40
|
+
@values = args
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# rubocop:enable Metrics/MethodLength
|
44
|
+
|
45
|
+
def obtain_full_post_text_line
|
46
|
+
return '' if @values.empty?
|
47
|
+
|
48
|
+
str_values = JSON.generate(Hash[@values.collect { |k| [k, 1] }])
|
49
|
+
nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
|
50
|
+
"eventType=customData&index=#{@id}&valuesCountMap=#{self.class.encode(str_values)}&overwrite=true&nonce=#{nonce}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'kameleoon/exceptions'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
NONCE_LENGTH = 16
|
8
|
+
|
9
|
+
module DataType
|
10
|
+
CUSTOM = 'CUSTOM'
|
11
|
+
BROWSER = 'BROWSER'
|
12
|
+
CONVERSION = 'CONVERSION'
|
13
|
+
DEVICE = 'DEVICE'
|
14
|
+
PAGE_VIEW = 'PAGE_VIEW'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Represents base class for any Kameleoon data
|
18
|
+
class Data
|
19
|
+
attr_reader :instance
|
20
|
+
attr_accessor :sent
|
21
|
+
|
22
|
+
def initialize(data_type)
|
23
|
+
@instance = data_type
|
24
|
+
@sent = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def obtain_full_post_text_line
|
28
|
+
raise KameleoonError.new('ToDo: implement this method.'), 'ToDo: implement this method.'
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.encode(url)
|
32
|
+
Network::UriHelper.encode_uri(url)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'data'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
module DeviceType
|
8
|
+
PHONE = 'PHONE'
|
9
|
+
TABLET = 'TABLET'
|
10
|
+
DESKTOP = 'DESKTOP'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Device uses for sending deviceType parameter for tracking calls
|
14
|
+
class Device < Data
|
15
|
+
attr_reader :device_type
|
16
|
+
def initialize(device_type)
|
17
|
+
super(DataType::DEVICE)
|
18
|
+
@device_type = device_type
|
19
|
+
end
|
20
|
+
|
21
|
+
def obtain_full_post_text_line
|
22
|
+
nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
|
23
|
+
"eventType=staticData&deviceType=#{@device_type}&nonce=#{nonce}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative 'data'
|
5
|
+
|
6
|
+
module Kameleoon
|
7
|
+
# Represents page view data for tracking calls
|
8
|
+
class PageView < Data
|
9
|
+
attr_reader :url, :title, :referrer
|
10
|
+
|
11
|
+
# @param [String] url Url of the page
|
12
|
+
# @param [String] title Title of the page
|
13
|
+
# @param [Array] referrers Optional field - Referrer ids
|
14
|
+
def initialize(url, title, referrers = nil)
|
15
|
+
super(DataType::PAGE_VIEW)
|
16
|
+
@url = url || ''
|
17
|
+
@title = title || ''
|
18
|
+
@referrers = referrers.instance_of?(Integer) ? [referrers] : referrers
|
19
|
+
end
|
20
|
+
|
21
|
+
def obtain_full_post_text_line
|
22
|
+
nonce = Kameleoon::Utils.generate_random_string(NONCE_LENGTH)
|
23
|
+
referrer_text = if !@referrers.nil? && !@referrers.empty?
|
24
|
+
"&referrersIndices=%5B#{@referrers.each(&:to_s).join('%2C')}%5D"
|
25
|
+
else
|
26
|
+
''
|
27
|
+
end
|
28
|
+
"eventType=page&href=#{self.class.encode(@url)}&title=#{self.class.encode(@title)}#{referrer_text}&nonce=#{nonce}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'kameleoon/data/data'
|
5
|
+
require 'kameleoon/utils'
|
6
|
+
require 'kameleoon/network/uri_helper'
|
7
|
+
|
8
|
+
module Kameleoon
|
9
|
+
module Network
|
10
|
+
##
|
11
|
+
# ActivityEvent represents an activity tracking event.
|
12
|
+
class ActivityEvent
|
13
|
+
EVENT_TYPE = 'activity'
|
14
|
+
|
15
|
+
attr_accessor :sent
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@sent = false
|
19
|
+
@nonce = Kameleoon::Utils.generate_random_string(Kameleoon::NONCE_LENGTH)
|
20
|
+
end
|
21
|
+
|
22
|
+
def obtain_full_post_text_line
|
23
|
+
params = {
|
24
|
+
eventType: EVENT_TYPE,
|
25
|
+
nonce: @nonce
|
26
|
+
}
|
27
|
+
UriHelper.encode_query(params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'kameleoon/data/data'
|
5
|
+
require 'kameleoon/utils'
|
6
|
+
require 'kameleoon/network/uri_helper'
|
7
|
+
|
8
|
+
module Kameleoon
|
9
|
+
module Network
|
10
|
+
##
|
11
|
+
# ExperimentEvent represents an experiment tracking event.
|
12
|
+
class ExperimentEvent
|
13
|
+
EVENT_TYPE = 'experiment'
|
14
|
+
|
15
|
+
attr_accessor :sent
|
16
|
+
|
17
|
+
def initialize(experiment_id, variation_id)
|
18
|
+
@sent = false
|
19
|
+
@experiment_id = experiment_id
|
20
|
+
@variation_id = variation_id
|
21
|
+
@nonce = Kameleoon::Utils.generate_random_string(Kameleoon::NONCE_LENGTH)
|
22
|
+
end
|
23
|
+
|
24
|
+
def obtain_full_post_text_line
|
25
|
+
params = {
|
26
|
+
eventType: EVENT_TYPE,
|
27
|
+
id: @experiment_id,
|
28
|
+
variationId: @variation_id,
|
29
|
+
nonce: @nonce
|
30
|
+
}
|
31
|
+
UriHelper.encode_query(params)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|