kameleoon-client-ruby 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kameleoon/client.rb +79 -133
  3. data/lib/kameleoon/configuration/rule.rb +1 -1
  4. data/lib/kameleoon/data/browser.rb +33 -0
  5. data/lib/kameleoon/data/conversion.rb +26 -0
  6. data/lib/kameleoon/data/custom_data.rb +53 -0
  7. data/lib/kameleoon/data/data.rb +35 -0
  8. data/lib/kameleoon/data/device.rb +26 -0
  9. data/lib/kameleoon/data/page_view.rb +31 -0
  10. data/lib/kameleoon/data/user_agent.rb +14 -0
  11. data/lib/kameleoon/network/activity_event.rb +31 -0
  12. data/lib/kameleoon/network/experiment_event.rb +35 -0
  13. data/lib/kameleoon/network/uri_helper.rb +36 -0
  14. data/lib/kameleoon/network/url_provider.rb +71 -0
  15. data/lib/kameleoon/request.rb +5 -19
  16. data/lib/kameleoon/targeting/condition.rb +40 -11
  17. data/lib/kameleoon/targeting/condition_factory.rb +35 -12
  18. data/lib/kameleoon/targeting/conditions/browser_condition.rb +71 -0
  19. data/lib/kameleoon/targeting/conditions/conversion_condition.rb +21 -0
  20. data/lib/kameleoon/targeting/conditions/custom_datum.rb +60 -65
  21. data/lib/kameleoon/targeting/conditions/device_condition.rb +21 -0
  22. data/lib/kameleoon/targeting/conditions/exclusive_experiment.rb +0 -12
  23. data/lib/kameleoon/targeting/conditions/page_title_condition.rb +21 -0
  24. data/lib/kameleoon/targeting/conditions/page_url_condition.rb +21 -0
  25. data/lib/kameleoon/targeting/conditions/sdk_language_condition.rb +65 -0
  26. data/lib/kameleoon/targeting/conditions/string_value_condition.rb +40 -0
  27. data/lib/kameleoon/targeting/conditions/target_experiment.rb +4 -8
  28. data/lib/kameleoon/targeting/conditions/unknown_condition.rb +15 -0
  29. data/lib/kameleoon/targeting/conditions/visitor_code_condition.rb +16 -0
  30. data/lib/kameleoon/targeting/models.rb +0 -24
  31. data/lib/kameleoon/utils.rb +1 -1
  32. data/lib/kameleoon/version.rb +28 -1
  33. metadata +22 -3
  34. data/lib/kameleoon/data.rb +0 -175
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba4f943be2e686ba2cca810ef8f456622e25733eda03808c7b3d81e2d72b1ee3
4
- data.tar.gz: cef2edf8ef8e449f3150f73c5df9d76477342a52e49fbf90885b458fd6aa1b57
3
+ metadata.gz: 1aef3f7b97d4a32024bec989ed4356cc1d10425c16b419b55f524cf1abfd4f52
4
+ data.tar.gz: 5705b067a3effc12b7f38ccef23e01ee28e370b99a212fd371ce0c863184c3ec
5
5
  SHA512:
6
- metadata.gz: 5b4e8f09c36222e08e9b426e90db6fb05476aa0e9bcd53036de31a8d7819db7b95ea5960adc6cc059494eb5355d9d912dd73a507923904723cf9ca63887adb4a
7
- data.tar.gz: 7f7f9d409053f873d9f7daa9b281b7c926d3b314fe5a2e7bd0814d3a7b5fdf4f8c5f61c6eed9f65a5fd4c3d11665a0efc5464164636e9affd0bac96f95d3798f
6
+ metadata.gz: 99cc273ca6010c9ce2c451e7a7cb3795e4b264b670fb8009436e5b9ddbaacf388e894f0922926bf92113ebf9f211636f4b4fc2a34fc01babcf848327bba798f8
7
+ data.tar.gz: 3686a34890b5438e5d0ca878cbb0bfb89386f2150267c73ef27754d207c6f918aad3355a312045251d3dea15fc2faa6558433f172b907ae4e913c7b60cc204f4
@@ -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
- @tracking_url = config['tracking_url'] || API_SSX_URL
43
- @api_data_url = 'https://api-data.kameleoon.com'
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
- if check_targeting(visitor_code, experiment_id, experiment)
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
- if !variation_id.nil?
136
- track_experiment(visitor_code, experiment_id, variation_id)
137
- save_variation(visitor_code, experiment_id, variation_id)
138
- variation_id
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
- track_data(visitor_code)
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 get_remote_date method allows you to retrieve data (according to a key passed as argument)
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 get_remote_date(key, timeout = @default_timeout)
401
+ def get_remote_data(key, timeout = @default_timeout)
399
402
  connexion_options = { connect_timeout: (timeout.to_f / 1000.0) }
400
- path = get_api_data_request_url(key)
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(@api_data_url + path, connexion_options)
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
- get_remote_date(key, timeout)
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(@site_code, @environment, time_stamp)
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
- events_url = "#{@events_url}sse?siteCode=#{@site_code}"
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(events_url, fetch_func, method(:log))
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(site_code, environment = @environment, time_stamp = nil)
582
+ def obtain_configuration(environment = @environment, time_stamp = nil)
581
583
  log 'Fetching configuration from Client-Config service'
582
- request_path = "mobile?siteCode=#{site_code}"
583
- request_path += "&environment=#{environment}" unless environment.nil?
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(path)
620
- request = EM::Synchrony.sync get({ path: path }, CLIENT_CONFIG_URL)
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
- save_variation(visitor_code, rule.experiment_id, variation.variation_id) unless variation.nil?
710
+ experiment_id = rule.experiment_id
794
711
  variation_id = variation.variation_id unless variation.nil?
795
- _send_tracking_request(visitor_code, rule.experiment_id, variation_id)
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.experiment_type?
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
- if !experiment_id.nil?
845
- variation_reference_id = variation_id || 0
846
- track_experiment(visitor_code, experiment_id, variation_reference_id)
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
- log 'An attempt to send a request with null experimentId was blocked'
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
 
@@ -45,7 +45,7 @@ module Kameleoon
45
45
  variation_by_exposition.select { |v| v.variation_key == key }.first&.variation_id
46
46
  end
47
47
 
48
- def experiment_type?
48
+ def experimentation_type?
49
49
  @type == RuleType::EXPERIMENTATION
50
50
  end
51
51
 
@@ -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,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Kameleoon
6
+ # UserAgent uses for changing User-Agent header for tracking calls
7
+ class UserAgent
8
+ attr_reader :value
9
+
10
+ def initialize(value)
11
+ @value = value
12
+ end
13
+ end
14
+ 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