vwo-sdk 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,102 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ require 'json'
18
+
19
+ class VWO
20
+ # Schema for verifying the settings_file provided by the customer
21
+ module Schema
22
+ SETTINGS_FILE_SCHEMA = {
23
+ type: 'object',
24
+ properties: {
25
+ version: {
26
+ type: %w[number string]
27
+ },
28
+ accountId: {
29
+ type: %w[number string]
30
+ },
31
+ campaigns: {
32
+ if: {
33
+ type: 'array'
34
+ },
35
+ then: {
36
+ minItems: 1,
37
+ items: {
38
+ '$ref' => '#/definitions/campaign_object_schema'
39
+ }
40
+ },
41
+ else: {
42
+ type: 'object',
43
+ maxProperties: 0
44
+ }
45
+ }
46
+ },
47
+ definitions: {
48
+ campaign_variation_schema: {
49
+ type: 'object',
50
+ properties: {
51
+ id: {
52
+ type: %w[number string]
53
+ },
54
+ name: {
55
+ type: ['string']
56
+ },
57
+ weight: {
58
+ type: %w[number string]
59
+ }
60
+ },
61
+ required: %w[id name weight]
62
+ },
63
+ campaign_object_schema: {
64
+ type: 'object',
65
+ properties: {
66
+ id: {
67
+ type: %w[number string]
68
+ },
69
+ key: {
70
+ type: ['string']
71
+ },
72
+ status: {
73
+ type: ['string']
74
+ },
75
+ percentTraffic: {
76
+ type: ['number']
77
+ },
78
+ variations: {
79
+ type: 'array',
80
+ items: {
81
+ '$ref' => '#/definitions/campaign_variation_schema'
82
+ }
83
+ },
84
+ minItems: 2
85
+ }
86
+ },
87
+ required: %w[
88
+ id
89
+ key
90
+ status
91
+ percentTraffic
92
+ variations
93
+ ]
94
+ },
95
+ required: %w[
96
+ version
97
+ accountId
98
+ campaigns
99
+ ]
100
+ }.freeze
101
+ end
102
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ require_relative '../logger'
18
+ require_relative '../enums'
19
+ require_relative '../utils/request'
20
+
21
+ class VWO
22
+ module Services
23
+ class EventDispatcher
24
+ include VWO::Enums
25
+
26
+ EXCLUDE_KEYS = ['url'].freeze
27
+
28
+ # Initialize the dispatcher with logger and development mode
29
+ #
30
+ # @param [Boolean] : To specify whether the request
31
+ # to our server should be made or not.
32
+ #
33
+ def initialize(is_development_mode = false)
34
+ @logger = VWO::Logger.get_instance
35
+ @is_development_mode = is_development_mode
36
+ end
37
+
38
+ # Dispatch the impression event having properties object only if dev-mode is OFF
39
+ #
40
+ # @param[Hash] :properties hash having impression properties
41
+ # the request to be dispatched to the VWO server
42
+ # @return[Boolean]
43
+ #
44
+ def dispatch(impression)
45
+ return true if @is_development_mode
46
+
47
+ modified_event = impression.reject do |key, _value|
48
+ EXCLUDE_KEYS.include?(key)
49
+ end
50
+
51
+ resp = VWO::Utils::Request.get(impression['url'], modified_event)
52
+ if resp.code == '200'
53
+ @logger.log(
54
+ LogLevelEnum::INFO,
55
+ format(
56
+ LogMessageEnum::InfoMessages::IMPRESSION_SUCCESS,
57
+ file: FileNameEnum::EventDispatcher,
58
+ end_point: impression[:url],
59
+ campaign_id: impression[:experiment_id],
60
+ user_id: impression[:uId],
61
+ account_id: impression[:account_id],
62
+ variation_id: impression[:combination]
63
+ )
64
+ )
65
+ return true
66
+ else
67
+ @logger.log(
68
+ LogLevelEnum::ERROR,
69
+ format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::EventDispatcher, end_point: impression['url'])
70
+ )
71
+ return false
72
+ end
73
+ rescue StandardError
74
+ @logger.log(
75
+ LogLevelEnum::ERROR,
76
+ format(LogMessageEnum::ErrorMessages::IMPRESSION_FAILED, file: FileNameEnum::EventDispatcher, end_point: impression['url'])
77
+ )
78
+ false
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ require_relative '../utils/function'
18
+ require_relative '../utils/request'
19
+ require_relative '../utils/validations'
20
+ require_relative '../constants'
21
+
22
+ class VWO
23
+ module Services
24
+ class SettingsFileManager
25
+ include ::VWO::Utils::Validations
26
+ include ::VWO::Utils::Function
27
+
28
+ PROTOCOL = 'https'
29
+ HOSTNAME = ::VWO::CONSTANTS::ENDPOINTS::BASE_URL
30
+ PATH = ::VWO::CONSTANTS::ENDPOINTS::ACCOUNT_SETTINGS
31
+
32
+ def initialize(account_id, sdk_key)
33
+ @account_id = account_id
34
+ @sdk_key = sdk_key
35
+ end
36
+
37
+ # Get Settings file method to retrieve settings_file for customer from VWO server
38
+ # @param [string]: Account ID of user
39
+ # @param [string]: Unique sdk key for user,
40
+ # can be retrieved from VWO app
41
+ # @return[string]: JSON - settings_file,
42
+ # as received from the server,
43
+ # nil if no settings_file is found or sdk_key is incorrect
44
+
45
+ def get_settings_file
46
+ is_valid_key = valid_number?(@account_id) || valid_string?(@account_id)
47
+
48
+ unless is_valid_key && valid_string?(@sdk_key)
49
+ STDERR.puts 'account_id and sdk_key are required for fetching account settings. Aborting!'
50
+ return '{}'
51
+ end
52
+
53
+ vwo_server_url = "#{PROTOCOL}://#{HOSTNAME}#{PATH}"
54
+
55
+ settings_file_response = ::VWO::Utils::Request.get(vwo_server_url, params)
56
+
57
+ if settings_file_response.code != '200'
58
+ message = <<-DOC
59
+ Request failed for fetching account settings.
60
+ Got Status Code: #{settings_file_response.code}
61
+ and message: #{settings_file_response.body}.
62
+ DOC
63
+ STDERR.puts message
64
+ return
65
+ end
66
+ settings_file_response.body
67
+ rescue StandardError => e
68
+ STDERR.puts "Error fetching Settings File #{e}"
69
+ end
70
+
71
+ private
72
+
73
+ def params
74
+ {
75
+ a: @account_id,
76
+ i: @sdk_key,
77
+ r: get_random_number,
78
+ platform: 'server',
79
+ 'api-version' => 1
80
+ }
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ require_relative '../logger'
18
+ require_relative '../enums'
19
+ require_relative '../utils/campaign'
20
+
21
+ class VWO
22
+ module Services
23
+ class SettingsFileProcessor
24
+ include VWO::Enums
25
+ include VWO::Utils::Campaign
26
+
27
+ # Method to initialize settings_file and logger
28
+ #
29
+ # @params
30
+ # settings_file (Hash): Hash object of setting
31
+ # representing the settings_file.
32
+
33
+ def initialize(settings_file)
34
+ @settings_file = JSON.parse(settings_file)
35
+ @logger = VWO::Logger.get_instance
36
+ end
37
+
38
+ # Processes the settings_file, assigns variation allocation range
39
+ def process_settings_file
40
+ (@settings_file['campaigns'] || []).each do |campaign|
41
+ set_variation_allocation(campaign)
42
+ end
43
+ @logger.log(
44
+ LogLevelEnum::DEBUG,
45
+ format(LogMessageEnum::DebugMessages::SETTINGS_FILE_PROCESSED, file: FileNameEnum::SettingsFileProcessor)
46
+ )
47
+ end
48
+
49
+ def get_settings_file
50
+ @settings_file
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ class VWO
18
+ # UserStorage Class is used to store user-variation mapping.
19
+ # Override this class to implement your own functionality.
20
+ # SDK will ensure to use this while bucketing a user into a variation.
21
+
22
+ class UserStorage
23
+ # To retrieve the stored variation for the user_id.
24
+ #
25
+ # @param[String] :user_id ID for user that needs to be retrieved.
26
+ # @param[String] :_campaign_key Unique campaign key
27
+ # @return[Hash] :user_data User's data.
28
+ #
29
+ def get(_user_id, _campaign_key); end
30
+
31
+ # To store the the user variation-mapping
32
+ # @param[Hash] :user_data
33
+ #
34
+ def set(_user_data); end
35
+ end
36
+ end
@@ -0,0 +1,125 @@
1
+ # Copyright 2019 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
+ # frozen_string_literal: true
16
+
17
+ require_relative '../logger'
18
+ require_relative '../enums'
19
+ require_relative '../constants'
20
+
21
+ # Utility module for processing VWO campaigns
22
+ class VWO
23
+ module Utils
24
+ module Campaign
25
+ include VWO::Enums
26
+ include VWO::CONSTANTS
27
+
28
+ # Finds and Returns campaign from given campaign_key.
29
+ #
30
+ # @param[Hash] :settings_file Settings file
31
+ # @param[String] :campaign_key Campaign identifier key
32
+ # @return[Hash] :campaign object
33
+
34
+ def get_campaign(settings_file, campaign_key)
35
+ (settings_file['campaigns'] || []).find do |campaign|
36
+ campaign['key'] == campaign_key
37
+ end
38
+ end
39
+
40
+ # Sets variation allocation range in the provided campaign
41
+ #
42
+ # @param [Hash]: Campaign object
43
+
44
+ def set_variation_allocation(campaign)
45
+ current_allocation = 0
46
+ campaign['variations'].each do |variation|
47
+ step_factor = get_variation_bucketing_range(variation['weight'])
48
+ if step_factor > 0
49
+ start_range = current_allocation + 1
50
+ end_range = current_allocation + step_factor
51
+ variation['start_variation_allocation'] = start_range
52
+ variation['end_variation_allocation'] = end_range
53
+ current_allocation += step_factor
54
+ else
55
+ variation['start_variation_allocation'] = -1
56
+ variation['end_variation_allocation'] = -1
57
+ end
58
+
59
+ VWO::Logger.get_instance.log(
60
+ LogLevelEnum::INFO,
61
+ format(
62
+ LogMessageEnum::InfoMessages::VARIATION_RANGE_ALLOCATION,
63
+ file: FileNameEnum::CampaignUtil,
64
+ campaign_key: campaign['key'],
65
+ variation_name: variation['name'],
66
+ variation_weight: variation['weight'],
67
+ start: variation['start_variation_allocation'],
68
+ end: variation['end_variation_allocation']
69
+ )
70
+ )
71
+ end
72
+ end
73
+
74
+ # Returns goal from given campaign_key and gaol_identifier.
75
+ # @param[Hash] :settings_file Settings file
76
+ # @param[String] :campaign_key Campaign identifier key
77
+ # @param[String] :goal_identifier Goal identifier
78
+ #
79
+ # @return[Hash] Goal corresponding to Goal_identifier in respective campaign
80
+
81
+ def get_campaign_goal(settings_file, campaign_key, goal_identifier)
82
+ return unless settings_file && campaign_key && goal_identifier
83
+
84
+ campaign = get_campaign(settings_file, campaign_key)
85
+ return unless campaign
86
+
87
+ campaign['goals'].find do |goal|
88
+ goal['identifier'] == goal_identifier
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ # Returns the bucket size of variation.
95
+ # @param (Number): weight of variation
96
+ # @return (Integer): Bucket start range of Variation
97
+
98
+ def get_variation_bucketing_range(weight)
99
+ return 0 if weight.nil? || weight == 0
100
+
101
+ start_range = (weight * 100).ceil.to_i
102
+ [start_range, MAX_TRAFFIC_VALUE].min
103
+ end
104
+
105
+ # Returns variation from given campaign_key and variation_name.
106
+ #
107
+ # @param[Hash] :settings_file Settings file
108
+ # @param[Hash] :campaign_key Campaign identifier key
109
+ # @param[String] :variation_name Variation identifier
110
+ #
111
+ # @return[Hash] Variation corresponding to variation_name in respective campaign
112
+
113
+ def get_campaign_variation(settings_file, campaign_key, variation_name)
114
+ return unless settings_file && campaign_key && variation_name
115
+
116
+ campaign = get_campaign(settings_file, campaign_key)
117
+ return unless campaign
118
+
119
+ campaign['variations'].find do |variation|
120
+ variation['name'] == variation_name
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end