diff --git a/optimizely/helpers/condition.py b/optimizely/helpers/condition.py
index 2cd80dde..57ec558c 100644
--- a/optimizely/helpers/condition.py
+++ b/optimizely/helpers/condition.py
@@ -26,6 +26,7 @@ class ConditionOperatorTypes(object):
     AND = 'and'
     OR = 'or'
     NOT = 'not'
+    operators = [AND, OR, NOT]
 
 
 class ConditionMatchTypes(object):
diff --git a/optimizely/lib/pymmh3.py b/optimizely/lib/pymmh3.py
index 0f107709..4997de21 100755
--- a/optimizely/lib/pymmh3.py
+++ b/optimizely/lib/pymmh3.py
@@ -127,25 +127,25 @@ def fmix(k):
         for block_start in xrange(0, nblocks * 8, 8):
             # ??? big endian?
             k1 = (
-                key[2 * block_start + 7] << 56
-                | key[2 * block_start + 6] << 48
-                | key[2 * block_start + 5] << 40
-                | key[2 * block_start + 4] << 32
-                | key[2 * block_start + 3] << 24
-                | key[2 * block_start + 2] << 16
-                | key[2 * block_start + 1] << 8
-                | key[2 * block_start + 0]
+                key[2 * block_start + 7] << 56 |
+                key[2 * block_start + 6] << 48 |
+                key[2 * block_start + 5] << 40 |
+                key[2 * block_start + 4] << 32 |
+                key[2 * block_start + 3] << 24 |
+                key[2 * block_start + 2] << 16 |
+                key[2 * block_start + 1] << 8 |
+                key[2 * block_start + 0]
             )
 
             k2 = (
-                key[2 * block_start + 15] << 56
-                | key[2 * block_start + 14] << 48
-                | key[2 * block_start + 13] << 40
-                | key[2 * block_start + 12] << 32
-                | key[2 * block_start + 11] << 24
-                | key[2 * block_start + 10] << 16
-                | key[2 * block_start + 9] << 8
-                | key[2 * block_start + 8]
+                key[2 * block_start + 15] << 56 |
+                key[2 * block_start + 14] << 48 |
+                key[2 * block_start + 13] << 40 |
+                key[2 * block_start + 12] << 32 |
+                key[2 * block_start + 11] << 24 |
+                key[2 * block_start + 10] << 16 |
+                key[2 * block_start + 9] << 8 |
+                key[2 * block_start + 8]
             )
 
             k1 = (c1 * k1) & 0xFFFFFFFFFFFFFFFF
@@ -258,31 +258,31 @@ def fmix(h):
         # body
         for block_start in xrange(0, nblocks * 16, 16):
             k1 = (
-                key[block_start + 3] << 24
-                | key[block_start + 2] << 16
-                | key[block_start + 1] << 8
-                | key[block_start + 0]
+                key[block_start + 3] << 24 |
+                key[block_start + 2] << 16 |
+                key[block_start + 1] << 8 |
+                key[block_start + 0]
             )
 
             k2 = (
-                key[block_start + 7] << 24
-                | key[block_start + 6] << 16
-                | key[block_start + 5] << 8
-                | key[block_start + 4]
+                key[block_start + 7] << 24 |
+                key[block_start + 6] << 16 |
+                key[block_start + 5] << 8 |
+                key[block_start + 4]
             )
 
             k3 = (
-                key[block_start + 11] << 24
-                | key[block_start + 10] << 16
-                | key[block_start + 9] << 8
-                | key[block_start + 8]
+                key[block_start + 11] << 24 |
+                key[block_start + 10] << 16 |
+                key[block_start + 9] << 8 |
+                key[block_start + 8]
             )
 
             k4 = (
-                key[block_start + 15] << 24
-                | key[block_start + 14] << 16
-                | key[block_start + 13] << 8
-                | key[block_start + 12]
+                key[block_start + 15] << 24 |
+                key[block_start + 14] << 16 |
+                key[block_start + 13] << 8 |
+                key[block_start + 12]
             )
 
             k1 = (c1 * k1) & 0xFFFFFFFF
diff --git a/optimizely/optimizely_config.py b/optimizely/optimizely_config.py
index f204263a..a5bb7566 100644
--- a/optimizely/optimizely_config.py
+++ b/optimizely/optimizely_config.py
@@ -12,13 +12,15 @@
 # limitations under the License.
 
 import copy
+from .helpers.condition import ConditionOperatorTypes
 
 from .project_config import ProjectConfig
 
 
 class OptimizelyConfig(object):
     def __init__(self, revision, experiments_map, features_map, datafile=None,
-                 sdk_key=None, environment_key=None, attributes=None, events=None):
+                 sdk_key=None, environment_key=None, attributes=None, events=None,
+                 audiences=None):
         self.revision = revision
         self.experiments_map = experiments_map
         self.features_map = features_map
@@ -27,6 +29,7 @@ def __init__(self, revision, experiments_map, features_map, datafile=None,
         self.environment_key = environment_key
         self.attributes = attributes or []
         self.events = events or []
+        self.audiences = audiences or []
 
     def get_datafile(self):
         """ Get the datafile associated with OptimizelyConfig.
@@ -36,44 +39,13 @@ def get_datafile(self):
         """
         return self._datafile
 
-    def get_sdk_key(self):
-        """ Get the sdk key associated with OptimizelyConfig.
-
-        Returns:
-            A string containing sdk key.
-        """
-        return self.sdk_key
-
-    def get_environment_key(self):
-        """ Get the environemnt key associated with OptimizelyConfig.
-
-        Returns:
-            A string containing environment key.
-        """
-        return self.environment_key
-
-    def get_attributes(self):
-        """ Get the attributes associated with OptimizelyConfig
-
-        returns:
-            A list of attributes.
-        """
-        return self.attributes
-
-    def get_events(self):
-        """ Get the events associated with OptimizelyConfig
-
-        returns:
-            A list of events.
-        """
-        return self.events
-
 
 class OptimizelyExperiment(object):
-    def __init__(self, id, key, variations_map):
+    def __init__(self, id, key, variations_map, audiences=''):
         self.id = id
         self.key = key
         self.variations_map = variations_map
+        self.audiences = audiences
 
 
 class OptimizelyFeature(object):
@@ -82,6 +54,8 @@ def __init__(self, id, key, experiments_map, variables_map):
         self.key = key
         self.experiments_map = experiments_map
         self.variables_map = variables_map
+        self.delivery_rules = []
+        self.experiment_rules = []
 
 
 class OptimizelyVariation(object):
@@ -113,6 +87,13 @@ def __init__(self, id, key, experiment_ids):
         self.experiment_ids = experiment_ids
 
 
+class OptimizelyAudience(object):
+    def __init__(self, id, name, conditions):
+        self.id = id
+        self.name = name
+        self.conditions = conditions
+
+
 class OptimizelyConfigService(object):
     """ Class encapsulating methods to be used in creating instance of OptimizelyConfig. """
 
@@ -136,9 +117,127 @@ def __init__(self, project_config):
         self.environment_key = project_config.environment_key
         self.attributes = project_config.attributes
         self.events = project_config.events
+        self.rollouts = project_config.rollouts
 
         self._create_lookup_maps()
 
+        '''
+            Merging typed_audiences with audiences from project_config.
+            The typed_audiences has higher precedence.
+        '''
+
+        typed_audiences = project_config.typed_audiences[:]
+        optly_typed_audiences = []
+        id_lookup_dict = {}
+        for typed_audience in typed_audiences:
+            optly_audience = OptimizelyAudience(
+                typed_audience.get('id'),
+                typed_audience.get('name'),
+                typed_audience.get('conditions')
+            )
+            optly_typed_audiences.append(optly_audience)
+            id_lookup_dict[typed_audience.get('id')] = typed_audience.get('id')
+
+        for old_audience in project_config.audiences:
+            # check if old_audience.id exists in new_audiences.id from typed_audiences
+            if old_audience.get('id') not in id_lookup_dict and old_audience.get('id') != "$opt_dummy_audience":
+                # Convert audiences lists to OptimizelyAudience array
+                optly_audience = OptimizelyAudience(
+                    old_audience.get('id'),
+                    old_audience.get('name'),
+                    old_audience.get('conditions')
+                )
+                optly_typed_audiences.append(optly_audience)
+
+        self.audiences = optly_typed_audiences
+
+    def replace_ids_with_names(self, conditions, audiences_map):
+        '''
+            Gets conditions and audiences_map [id:name]
+
+            Returns:
+                a string of conditions with id's swapped with names
+                or empty string if no conditions found.
+
+        '''
+        if conditions is not None:
+            return self.stringify_conditions(conditions, audiences_map)
+        else:
+            return ''
+
+    def lookup_name_from_id(self, audience_id, audiences_map):
+        '''
+            Gets and audience ID and audiences map
+
+            Returns:
+                The name corresponding to the ID
+                or '' if not found.
+        '''
+        name = None
+        try:
+            name = audiences_map[audience_id]
+        except KeyError:
+            name = audience_id
+
+        return name
+
+    def stringify_conditions(self, conditions, audiences_map):
+        '''
+            Gets a list of conditions from an entities.Experiment
+            and an audiences_map [id:name]
+
+            Returns:
+                A string of conditions and names for the provided
+                list of conditions.
+        '''
+        ARGS = ConditionOperatorTypes.operators
+        operand = 'OR'
+        conditions_str = ''
+        length = len(conditions)
+
+        # Edge cases for lengths 0, 1 or 2
+        if length == 0:
+            return ''
+        if length == 1 and conditions[0] not in ARGS:
+            return '"' + self.lookup_name_from_id(conditions[0], audiences_map) + '"'
+        if length == 2 and conditions[0] in ARGS and \
+            type(conditions[1]) is not list and \
+                conditions[1] not in ARGS:
+            if conditions[0] != "not":
+                return '"' + self.lookup_name_from_id(conditions[1], audiences_map) + '"'
+            else:
+                return conditions[0].upper() + \
+                    ' "' + self.lookup_name_from_id(conditions[1], audiences_map) + '"'
+        # If length is 2 (where the one elemnt is a list) or greater
+        if length > 1:
+            for i in range(length):
+                # Operand is handled here and made Upper Case
+                if conditions[i] in ARGS:
+                    operand = conditions[i].upper()
+                else:
+                    # Check if element is a list or not
+                    if type(conditions[i]) == list:
+                        # Check if at the end or not to determine where to add the operand
+                        # Recursive call to call stringify on embedded list
+                        if i + 1 < length:
+                            conditions_str += '(' + self.stringify_conditions(conditions[i], audiences_map) + ') '
+                        else:
+                            conditions_str += operand + \
+                                ' (' + self.stringify_conditions(conditions[i], audiences_map) + ')'
+                    # If the item is not a list, we process as an audience ID and retrieve the name
+                    else:
+                        audience_name = self.lookup_name_from_id(conditions[i], audiences_map)
+                        if audience_name is not None:
+                            # Below handles all cases for one ID or greater
+                            if i + 1 < length - 1:
+                                conditions_str += '"' + audience_name + '" ' + operand + ' '
+                            elif i + 1 == length:
+                                conditions_str += operand + ' "' + audience_name + '"'
+                            else:
+                                conditions_str += '"' + audience_name + '" '
+
+        return conditions_str or ''
+
     def get_config(self):
         """ Gets instance of OptimizelyConfig
 
@@ -159,8 +258,10 @@ def get_config(self):
             self._datafile,
             self.sdk_key,
             self.environment_key,
-            self.attributes,
-            self.events)
+            self._get_attributes_list(self.attributes),
+            self._get_events_list(self.events),
+            self.audiences
+        )
 
     def _create_lookup_maps(self):
         """ Creates lookup maps to avoid redundant iteration of config objects.  """
@@ -248,7 +349,8 @@ def _get_all_experiments(self):
         return experiments
 
     def _get_experiments_maps(self):
-        """ Gets maps for all the experiments in the project config.
+        """ Gets maps for all the experiments in the project config and
+        updates the experiment with updated experiment audiences string.
 
         Returns:
             dict, dict -- experiment key/id to OptimizelyExperiment maps.
@@ -257,12 +359,21 @@ def _get_experiments_maps(self):
         experiments_key_map = {}
         # Id map comes in handy to figure out feature experiment.
         experiments_id_map = {}
+        # Audiences map to use for updating experiments with new audience conditions string
+        audiences_map = {}
+
+        # Build map from OptimizelyAudience array
+        for optly_audience in self.audiences:
+            audiences_map[optly_audience.id] = optly_audience.name
 
         all_experiments = self._get_all_experiments()
         for exp in all_experiments:
             optly_exp = OptimizelyExperiment(
                 exp['id'], exp['key'], self._get_variations_map(exp)
             )
+            # Updating each OptimizelyExperiment
+            audiences = self.replace_ids_with_names(exp.get('audienceConditions', []), audiences_map)
+            optly_exp.audiences = audiences or ''
 
             experiments_key_map[exp['key']] = optly_exp
             experiments_id_map[exp['id']] = optly_exp
@@ -279,19 +390,96 @@ def _get_features_map(self, experiments_id_map):
             dict -- feaure key to OptimizelyFeature map
         """
         features_map = {}
+        experiment_rules = []
 
         for feature in self.feature_flags:
+
+            delivery_rules = self._get_delivery_rules(self.rollouts, feature.get('rolloutId'))
+            experiment_rules = []
+
             exp_map = {}
             for experiment_id in feature.get('experimentIds', []):
                 optly_exp = experiments_id_map[experiment_id]
                 exp_map[optly_exp.key] = optly_exp
+                experiment_rules.append(optly_exp)
 
             variables_map = self.feature_key_variable_key_to_variable_map[feature['key']]
 
             optly_feature = OptimizelyFeature(
                 feature['id'], feature['key'], exp_map, variables_map
             )
+            optly_feature.experiment_rules = experiment_rules
+            optly_feature.delivery_rules = delivery_rules
 
             features_map[feature['key']] = optly_feature
 
         return features_map
+
+    def _get_delivery_rules(self, rollouts, rollout_id):
+        """ Gets an array of rollouts for the project config
+
+        returns:
+            an array of OptimizelyExperiments as delivery rules.
+        """
+        # Return list for delivery rules
+        delivery_rules = []
+        # Audiences map to use for updating experiments with new audience conditions string
+        audiences_map = {}
+
+        # Gets a rollout based on provided rollout_id
+        rollout = [rollout for rollout in rollouts if rollout.get('id') == rollout_id]
+
+        if rollout:
+            rollout = rollout[0]
+            # Build map from OptimizelyAudience array
+            for optly_audience in self.audiences:
+                audiences_map[optly_audience.id] = optly_audience.name
+
+            # Get the experiments_map for that rollout
+            experiments = rollout.get('experiments_map')
+            if experiments:
+                for experiment in experiments:
+                    optly_exp = OptimizelyExperiment(
+                        experiment['id'], experiment['key'], self._get_variations_map(experiment)
+                    )
+                    audiences = self.replace_ids_with_names(experiment.get('audienceConditions', []), audiences_map)
+                    optly_exp.audiences = audiences
+
+                    delivery_rules.append(optly_exp)
+
+        return delivery_rules
+
+    def _get_attributes_list(self, attributes):
+        """ Gets attributes list for the project config
+
+        Returns:
+            List - OptimizelyAttributes
+        """
+        attributes_list = []
+
+        for attribute in attributes:
+            optly_attribute = OptimizelyAttribute(
+                attribute['id'],
+                attribute['key']
+            )
+            attributes_list.append(optly_attribute)
+
+        return attributes_list
+
+    def _get_events_list(self, events):
+        """ Gets events list for the project_config
+
+        Returns:
+            List - OptimizelyEvents
+        """
+        events_list = []
+
+        for event in events:
+            optly_event = OptimizelyEvent(
+                event['id'],
+                event['key'],
+                event['experimentIds']
+            )
+            events_list.append(optly_event)
+
+        return events_list
diff --git a/tests/base.py b/tests/base.py
index 48b89106..05127caf 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -756,7 +756,8 @@ def setUp(self, config_dict='config_dict'):
             'projectId': '11624721371',
             'variables': [],
             'featureFlags': [
-                {'experimentIds': [], 'rolloutId': '11551226731', 'variables': [], 'id': '11477755619', 'key': 'feat'},
+                {'experimentIds': [], 'rolloutId': '11551226731', 'variables': [], 'id': '11477755619',
+                    'key': 'feat'},
                 {
                     'experimentIds': ['11564051718'],
                     'rolloutId': '11638870867',
diff --git a/tests/test_optimizely_config.py b/tests/test_optimizely_config.py
index 29bd2443..b7cbbd7b 100644
--- a/tests/test_optimizely_config.py
+++ b/tests/test_optimizely_config.py
@@ -13,7 +13,7 @@
 
 import json
 
-from optimizely import optimizely
+from optimizely import optimizely, project_config
 from optimizely import optimizely_config
 from . import base
 
@@ -29,7 +29,27 @@ def setUp(self):
             'sdk_key': None,
             'environment_key': None,
             'attributes': [{'key': 'test_attribute', 'id': '111094'}],
-            'events': [{'key': 'test_event', 'experimentIds': ['111127'], 'id': '111095'}],
+            'events': [{'key': 'test_event', 'experiment_ids': ['111127'], 'id': '111095'}],
+            'audiences': [
+                {
+                    'name': 'Test attribute users 1',
+                    'conditions': '["and", ["or", ["or", '
+                    '{"name": "test_attribute", "type": "custom_attribute", "value": "test_value_1"}]]]',
+                    'id': '11154'
+                },
+                {
+                    'name': 'Test attribute users 2',
+                    'conditions': '["and", ["or", ["or", '
+                    '{"name": "test_attribute", "type": "custom_attribute", "value": "test_value_2"}]]]',
+                    'id': '11159'
+                },
+                {
+                    'name': 'Test attribute users 3',
+                    'conditions': "[\"and\", [\"or\", [\"or\", {\"match\": \"exact\", \"name\": \
+                        \"experiment_attr\", \"type\": \"custom_attribute\", \"value\": \"group_experiment\"}]]]",
+                    'id': '11160',
+                }
+            ],
             'experiments_map': {
                 'test_experiment2': {
                     'variations_map': {
@@ -51,7 +71,8 @@ def setUp(self):
                         }
                     },
                     'id': '111133',
-                    'key': 'test_experiment2'
+                    'key': 'test_experiment2',
+                    'audiences': ''
                 },
                 'test_experiment': {
                     'variations_map': {
@@ -155,7 +176,8 @@ def setUp(self):
                         }
                     },
                     'id': '111127',
-                    'key': 'test_experiment'
+                    'key': 'test_experiment',
+                    'audiences': ''
                 },
                 'group_exp_1': {
                     'variations_map': {
@@ -177,7 +199,8 @@ def setUp(self):
                         }
                     },
                     'id': '32222',
-                    'key': 'group_exp_1'
+                    'key': 'group_exp_1',
+                    'audiences': ''
                 },
                 'group_exp_2': {
                     'variations_map': {
@@ -199,7 +222,8 @@ def setUp(self):
                         }
                     },
                     'id': '32223',
-                    'key': 'group_exp_2'
+                    'key': 'group_exp_2',
+                    'audiences': ''
                 },
                 'group_2_exp_1': {
                     'variations_map': {
@@ -213,7 +237,8 @@ def setUp(self):
                         },
                     },
                     'id': '42222',
-                    'key': 'group_2_exp_1'
+                    'key': 'group_2_exp_1',
+                    'audiences': '"Test attribute users 3"'
                 },
                 'group_2_exp_2': {
                     'variations_map': {
@@ -227,7 +252,8 @@ def setUp(self):
                         },
                     },
                     'id': '42223',
-                    'key': 'group_2_exp_2'
+                    'key': 'group_2_exp_2',
+                    'audiences': '"Test attribute users 3"'
                 },
                 'group_2_exp_3': {
                     'variations_map': {
@@ -241,7 +267,8 @@ def setUp(self):
                         },
                     },
                     'id': '42224',
-                    'key': 'group_2_exp_3'
+                    'key': 'group_2_exp_3',
+                    'audiences': '"Test attribute users 3"'
                 },
                 'test_experiment3': {
                     'variations_map': {
@@ -255,7 +282,8 @@ def setUp(self):
                         },
                     },
                     'id': '111134',
-                    'key': 'test_experiment3'
+                    'key': 'test_experiment3',
+                    'audiences': '"Test attribute users 3"'
                 },
                 'test_experiment4': {
                     'variations_map': {
@@ -269,7 +297,8 @@ def setUp(self):
                         },
                     },
                     'id': '111135',
-                    'key': 'test_experiment4'
+                    'key': 'test_experiment4',
+                    'audiences': '"Test attribute users 3"'
                 },
                 'test_experiment5': {
                     'variations_map': {
@@ -283,7 +312,8 @@ def setUp(self):
                         },
                     },
                     'id': '111136',
-                    'key': 'test_experiment5'
+                    'key': 'test_experiment5',
+                    'audiences': '"Test attribute users 3"'
                 }
             },
             'features_map': {
@@ -435,9 +465,118 @@ def setUp(self):
                                 }
                             },
                             'id': '111127',
-                            'key': 'test_experiment'
+                            'key': 'test_experiment',
+                            'audiences': ''
                         }
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [
+                        {
+                            'id': '111127',
+                            'key': 'test_experiment',
+                            'variations_map': {
+                                'control': {
+                                    'id': '111128',
+                                    'key': 'control',
+                                    'feature_enabled': False,
+                                    'variables_map': {
+                                        'is_working': {
+                                            'id': '127',
+                                            'key': 'is_working',
+                                            'type': 'boolean',
+                                            'value': 'true'
+                                        },
+                                        'environment': {
+                                            'id': '128',
+                                            'key': 'environment',
+                                            'type': 'string',
+                                            'value': 'devel'
+                                        },
+                                        'cost': {
+                                            'id': '129',
+                                            'key': 'cost',
+                                            'type': 'double',
+                                            'value': '10.99'
+                                        },
+                                        'count': {
+                                            'id': '130',
+                                            'key': 'count',
+                                            'type': 'integer',
+                                            'value': '999'
+                                        },
+                                        'variable_without_usage': {
+                                            'id': '131',
+                                            'key': 'variable_without_usage',
+                                            'type': 'integer',
+                                            'value': '45'
+                                        },
+                                        'object': {
+                                            'id': '132',
+                                            'key': 'object',
+                                            'type': 'json',
+                                            'value': '{"test": 12}'
+                                        },
+                                        'true_object': {
+                                            'id': '133',
+                                            'key': 'true_object',
+                                            'type': 'json',
+                                            'value': '{"true_test": 23.54}'
+                                        }
+                                    }
+                                },
+                                'variation': {
+                                    'id': '111129',
+                                    'key': 'variation',
+                                    'feature_enabled': True,
+                                    'variables_map': {
+                                        'is_working': {
+                                            'id': '127',
+                                            'key': 'is_working',
+                                            'type': 'boolean',
+                                            'value': 'true'
+                                        },
+                                        'environment': {
+                                            'id': '128',
+                                            'key': 'environment',
+                                            'type': 'string',
+                                            'value': 'staging'
+                                        },
+                                        'cost': {
+                                            'id': '129',
+                                            'key': 'cost',
+                                            'type': 'double',
+                                            'value': '10.02'
+                                        },
+                                        'count': {
+                                            'id': '130',
+                                            'key': 'count',
+                                            'type': 'integer',
+                                            'value': '4243'
+                                        },
+                                        'variable_without_usage': {
+                                            'id': '131',
+                                            'key': 'variable_without_usage',
+                                            'type': 'integer',
+                                            'value': '45'
+                                        },
+                                        'object': {
+                                            'id': '132',
+                                            'key': 'object',
+                                            'type': 'json',
+                                            'value': '{"test": 123}'
+                                        },
+                                        'true_object': {
+                                            'id': '133',
+                                            'key': 'true_object',
+                                            'type': 'json',
+                                            'value': '{"true_test": 1.4}'
+                                        }
+                                    }
+                                }
+                            },
+                            'audiences': ''
+                        }
+                    ],
                     'id': '91111',
                     'key': 'test_feature_in_experiment'
                 },
@@ -477,6 +616,8 @@ def setUp(self):
                     'experiments_map': {
 
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [],
                     'id': '91112',
                     'key': 'test_feature_in_rollout'
                 },
@@ -505,9 +646,32 @@ def setUp(self):
                                 }
                             },
                             'id': '32222',
-                            'key': 'group_exp_1'
+                            'key': 'group_exp_1',
+                            'audiences': ''
                         }
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [
+                        {
+                            'id': '32222',
+                            'key': 'group_exp_1',
+                            'variations_map': {
+                                'group_exp_1_control': {
+                                    'id': '28901',
+                                    'key': 'group_exp_1_control',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                },
+                                'group_exp_1_variation': {
+                                    'id': '28902',
+                                    'key': 'group_exp_1_variation',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': ''
+                        }
+                    ],
                     'id': '91113',
                     'key': 'test_feature_in_group'
                 },
@@ -536,9 +700,32 @@ def setUp(self):
                                 }
                             },
                             'id': '32223',
-                            'key': 'group_exp_2'
+                            'key': 'group_exp_2',
+                            'audiences': ''
                         }
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [
+                        {
+                            'id': '32223',
+                            'key': 'group_exp_2',
+                            'variations_map': {
+                                'group_exp_2_control': {
+                                    'id': '28905',
+                                    'key': 'group_exp_2_control',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                },
+                                'group_exp_2_variation': {
+                                    'id': '28906',
+                                    'key': 'group_exp_2_variation',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': ''
+                        }
+                    ],
                     'id': '91114',
                     'key': 'test_feature_in_experiment_and_rollout'
                 },
@@ -559,7 +746,8 @@ def setUp(self):
                                 },
                             },
                             'id': '42222',
-                            'key': 'group_2_exp_1'
+                            'key': 'group_2_exp_1',
+                            'audiences': '"Test attribute users 3"'
                         },
                         'group_2_exp_2': {
                             'variations_map': {
@@ -573,7 +761,8 @@ def setUp(self):
                                 },
                             },
                             'id': '42223',
-                            'key': 'group_2_exp_2'
+                            'key': 'group_2_exp_2',
+                            'audiences': '"Test attribute users 3"'
                         },
                         'group_2_exp_3': {
                             'variations_map': {
@@ -587,9 +776,52 @@ def setUp(self):
                                 },
                             },
                             'id': '42224',
-                            'key': 'group_2_exp_3'
+                            'key': 'group_2_exp_3',
+                            'audiences': '"Test attribute users 3"'
                         }
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [
+                        {
+                            'id': '42222',
+                            'key': 'group_2_exp_1',
+                            'variations_map': {
+                                'var_1': {
+                                    'id': '38901',
+                                    'key': 'var_1',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        },
+                        {
+                            'id': '42223',
+                            'key': 'group_2_exp_2',
+                            'variations_map': {
+                                'var_1': {
+                                    'id': '38905',
+                                    'key': 'var_1',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        },
+                        {
+                            'id': '42224',
+                            'key': 'group_2_exp_3',
+                            'variations_map': {
+                                'var_1': {
+                                    'id': '38906',
+                                    'key': 'var_1',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        }
+                    ],
                     'id': '91115',
                     'key': 'test_feature_in_exclusion_group'
                 },
@@ -610,7 +842,8 @@ def setUp(self):
                                 },
                             },
                             'id': '111134',
-                            'key': 'test_experiment3'
+                            'key': 'test_experiment3',
+                            'audiences': '"Test attribute users 3"'
                         },
                         'test_experiment4': {
                             'variations_map': {
@@ -624,7 +857,8 @@ def setUp(self):
                                 },
                             },
                             'id': '111135',
-                            'key': 'test_experiment4'
+                            'key': 'test_experiment4',
+                            'audiences': '"Test attribute users 3"'
                         },
                         'test_experiment5': {
                             'variations_map': {
@@ -638,9 +872,52 @@ def setUp(self):
                                 },
                             },
                             'id': '111136',
-                            'key': 'test_experiment5'
+                            'key': 'test_experiment5',
+                            'audiences': '"Test attribute users 3"'
                         }
                     },
+                    'delivery_rules': [],
+                    'experiment_rules': [
+                        {
+                            'id': '111134',
+                            'key': 'test_experiment3',
+                            'variations_map': {
+                                'control': {
+                                    'id': '222239',
+                                    'key': 'control',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        },
+                        {
+                            'id': '111135',
+                            'key': 'test_experiment4',
+                            'variations_map': {
+                                'control': {
+                                    'id': '222240',
+                                    'key': 'control',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        },
+                        {
+                            'id': '111136',
+                            'key': 'test_experiment5',
+                            'variations_map': {
+                                'control': {
+                                    'id': '222241',
+                                    'key': 'control',
+                                    'feature_enabled': None,
+                                    'variables_map': {}
+                                }
+                            },
+                            'audiences': '"Test attribute users 3"'
+                        }
+                    ],
                     'id': '91116',
                     'key': 'test_feature_in_multiple_experiments'
                 }
@@ -652,6 +929,209 @@ def setUp(self):
         self.actual_config = self.opt_config_service.get_config()
         self.actual_config_dict = self.to_dict(self.actual_config)
 
+        self.typed_audiences_config = {
+            'version': '2',
+            'rollouts': [],
+            'projectId': '10431130345',
+            'variables': [],
+            'featureFlags': [],
+            'experiments': [
+                {
+                    'status': 'Running',
+                    'key': 'ab_running_exp_untargeted',
+                    'layerId': '10417730432',
+                    'trafficAllocation': [{'entityId': '10418551353', 'endOfRange': 10000}],
+                    'audienceIds': [],
+                    'variations': [
+                        {'variables': [], 'id': '10418551353', 'key': 'all_traffic_variation'},
+                        {'variables': [], 'id': '10418510624', 'key': 'no_traffic_variation'},
+                    ],
+                    'forcedVariations': {},
+                    'id': '10420810910',
+                }
+            ],
+            'audiences': [
+                {
+                    'id': '3468206642',
+                    'name': 'exactString',
+                    'conditions': '["and", ["or", ["or", {"name": "house", '
+                                  '"type": "custom_attribute", "value": "Gryffindor"}]]]',
+                },
+                {
+                    'id': '3988293898',
+                    'name': '$$dummySubstringString',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3988293899',
+                    'name': '$$dummyExists',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3468206646',
+                    'name': '$$dummyExactNumber',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3468206647',
+                    'name': '$$dummyGtNumber',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3468206644',
+                    'name': '$$dummyLtNumber',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3468206643',
+                    'name': '$$dummyExactBoolean',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '3468206645',
+                    'name': '$$dummyMultipleCustomAttrs',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+                {
+                    'id': '0',
+                    'name': '$$dummy',
+                    'conditions': '{ "type": "custom_attribute", '
+                                  '"name": "$opt_dummy_attribute", "value": "impossible_value" }',
+                },
+            ],
+            'typedAudiences': [
+                {
+                    'id': '3988293898',
+                    'name': 'substringString',
+                    'conditions': [
+                        'and',
+                        [
+                            'or',
+                            [
+                                'or',
+                                {
+                                    'name': 'house',
+                                    'type': 'custom_attribute',
+                                    'match': 'substring',
+                                    'value': 'Slytherin',
+                                },
+                            ],
+                        ],
+                    ],
+                },
+                {
+                    'id': '3988293899',
+                    'name': 'exists',
+                    'conditions': [
+                        'and',
+                        [
+                            'or',
+                            ['or', {'name': 'favorite_ice_cream', 'type': 'custom_attribute', 'match': 'exists'}],
+                        ],
+                    ],
+                },
+                {
+                    'id': '3468206646',
+                    'name': 'exactNumber',
+                    'conditions': [
+                        'and',
+                        [
+                            'or',
+                            ['or', {'name': 'lasers', 'type': 'custom_attribute', 'match': 'exact', 'value': 45.5}],
+                        ],
+                    ],
+                },
+                {
+                    'id': '3468206647',
+                    'name': 'gtNumber',
+                    'conditions': [
+                        'and',
+                        ['or', ['or', {'name': 'lasers', 'type': 'custom_attribute', 'match': 'gt', 'value': 70}]],
+                    ],
+                },
+                {
+                    'id': '3468206644',
+                    'name': 'ltNumber',
+                    'conditions': [
+                        'and',
+                        ['or', ['or', {'name': 'lasers', 'type': 'custom_attribute', 'match': 'lt', 'value': 1.0}]],
+                    ],
+                },
+                {
+                    'id': '3468206643',
+                    'name': 'exactBoolean',
+                    'conditions': [
+                        'and',
+                        [
+                            'or',
+                            [
+                                'or',
+                                {'name': 'should_do_it', 'type': 'custom_attribute', 'match': 'exact', 'value': True},
+                            ],
+                        ],
+                    ],
+                },
+                {
+                    'id': '3468206645',
+                    'name': 'multiple_custom_attrs',
+                    'conditions': [
+                        "and",
+                        [
+                            "or",
+                            [
+                                "or",
+                                {"type": "custom_attribute", "name": "browser", "value": "chrome"},
+                                {"type": "custom_attribute", "name": "browser", "value": "firefox"},
+                            ],
+                        ],
+                    ],
+                },
+                {
+                    "id": "18278344267",
+                    "name": "semverReleaseLt1.2.3Gt1.0.0",
+                    "conditions": [
+                        "and",
+                        [
+                            "or",
+                            [
+                                "or",
+                                {
+                                    "value": "1.2.3",
+                                    "type": "custom_attribute",
+                                    "name": "android-release",
+                                    "match": "semver_lt"
+                                }
+                            ]
+                        ],
+                        [
+                            "or",
+                            [
+                                "or",
+                                {
+                                    "value": "1.0.0",
+                                    "type": "custom_attribute",
+                                    "name": "android-release",
+                                    "match": "semver_gt"
+                                }
+                            ]
+                        ]
+                    ]
+                }
+            ],
+            'groups': [],
+            'attributes': [],
+            'accountId': '10367498574',
+            'events': [{'experimentIds': ['10420810910'], 'id': '10404198134', 'key': 'winning'}],
+            'revision': '1337',
+        }
+
     def to_dict(self, obj):
         return json.loads(json.dumps(obj, default=lambda o: o.__dict__))
 
@@ -749,7 +1229,7 @@ def test__get_sdk_key(self):
 
         expected_value = 'testSdkKey'
 
-        self.assertEqual(expected_value, config.get_sdk_key())
+        self.assertEqual(expected_value, config.sdk_key)
 
     def test__get_sdk_key_invalid(self):
         """ Negative Test that tests get_sdk_key does not return the expected value. """
@@ -763,7 +1243,7 @@ def test__get_sdk_key_invalid(self):
 
         invalid_value = 123
 
-        self.assertNotEqual(invalid_value, config.get_sdk_key())
+        self.assertNotEqual(invalid_value, config.sdk_key)
 
     def test__get_environment_key(self):
         """ Test that get_environment_key returns the expected value. """
@@ -777,7 +1257,7 @@ def test__get_environment_key(self):
 
         expected_value = 'TestEnvironmentKey'
 
-        self.assertEqual(expected_value, config.get_environment_key())
+        self.assertEqual(expected_value, config.environment_key)
 
     def test__get_environment_key_invalid(self):
         """ Negative Test that tests get_environment_key does not return the expected value. """
@@ -791,7 +1271,7 @@ def test__get_environment_key_invalid(self):
 
         invalid_value = 321
 
-        self.assertNotEqual(invalid_value, config.get_environment_key())
+        self.assertNotEqual(invalid_value, config.environment_key)
 
     def test__get_attributes(self):
         """ Test that the get_attributes returns the expected value. """
@@ -819,8 +1299,8 @@ def test__get_attributes(self):
             'key': '234'
         }]
 
-        self.assertEqual(expected_value, config.get_attributes())
-        self.assertEqual(len(config.get_attributes()), 2)
+        self.assertEqual(expected_value, config.attributes)
+        self.assertEqual(len(config.attributes), 2)
 
     def test__get_events(self):
         """ Test that the get_events returns the expected value. """
@@ -861,5 +1341,128 @@ def test__get_events(self):
             }
         }]
 
-        self.assertEqual(expected_value, config.get_events())
-        self.assertEqual(len(config.get_events()), 2)
+        self.assertEqual(expected_value, config.events)
+        self.assertEqual(len(config.events), 2)
+
+    def test_get_audiences(self):
+        ''' Test to confirm get_audiences returns proper value '''
+        config_dict = self.typed_audiences_config
+
+        proj_conf = project_config.ProjectConfig(
+            json.dumps(config_dict),
+            logger=None,
+            error_handler=None
+        )
+
+        config_service = optimizely_config.OptimizelyConfigService(proj_conf)
+
+        for audience in config_service.audiences:
+            self.assertIsInstance(audience, optimizely_config.OptimizelyAudience)
+
+        config = config_service.get_config()
+
+        for audience in config.audiences:
+            self.assertIsInstance(audience, optimizely_config.OptimizelyAudience)
+
+        self.assertEqual(len(config.audiences), len(config_service.audiences))
+
+    def test_stringify_audience_conditions_all_cases(self):
+        audiences_map = {
+            '1': 'us',
+            '2': 'female',
+            '3': 'adult',
+            '11': 'fr',
+            '12': 'male',
+            '13': 'kid'
+        }
+
+        config = optimizely_config.OptimizelyConfig(
+            revision='101',
+            experiments_map={},
+            features_map={},
+            environment_key='TestEnvironmentKey',
+            attributes={},
+            events={},
+            audiences=None
+        )
+
+        audiences_input = [
+            [],
+            ["or", "1", "2"],
+            ["and", "1", "2", "3"],
+            ["not", "1"],
+            ["or", "1"],
+            ["and", "1"],
+            ["1"],
+            ["1", "2"],
+            ["and", ["or", "1", "2"], "3"],
+            ["and", ["or", "1", ["and", "2", "3"]], ["and", "11", ["or", "12", "13"]]],
+            ["not", ["and", "1", "2"]],
+            ["or", "1", "100000"],
+            ["and", "and"],
+            ["and"]
+        ]
+
+        audiences_output = [
+            '',
+            '"us" OR "female"',
+            '"us" AND "female" AND "adult"',
+            'NOT "us"',
+            '"us"',
+            '"us"',
+            '"us"',
+            '"us" OR "female"',
+            '("us" OR "female") AND "adult"',
+            '("us" OR ("female" AND "adult")) AND ("fr" AND ("male" OR "kid"))',
+            'NOT ("us" AND "female")',
+            '"us" OR "100000"',
+            '',
+            ''
+        ]
+
+        config_service = optimizely_config.OptimizelyConfigService(config)
+
+        for i in range(len(audiences_input)):
+            result = config_service.stringify_conditions(audiences_input[i], audiences_map)
+            self.assertEqual(audiences_output[i], result)
+
+    def test_optimizely_audience_conversion(self):
+        ''' Test to confirm that audience conversion works and has expected output '''
+        config_dict = self.typed_audiences_config
+
+        TOTAL_AUDEINCES_ONCE_MERGED = 10
+
+        proj_conf = project_config.ProjectConfig(
+            json.dumps(config_dict),
+            logger=None,
+            error_handler=None
+        )
+
+        config_service = optimizely_config.OptimizelyConfigService(proj_conf)
+
+        for audience in config_service.audiences:
+            self.assertIsInstance(audience, optimizely_config.OptimizelyAudience)
+
+        self.assertEqual(len(config_service.audiences), TOTAL_AUDEINCES_ONCE_MERGED)
+
+    def test_get_variations_from_experiments_map(self):
+        config_dict = self.typed_audiences_config
+
+        proj_conf = project_config.ProjectConfig(
+            json.dumps(config_dict),
+            logger=None,
+            error_handler=None
+        )
+
+        config_service = optimizely_config.OptimizelyConfigService(proj_conf)
+
+        experiments_key_map, experiments_id_map = config_service._get_experiments_maps()
+
+        optly_experiment = experiments_id_map['10420810910']
+
+        for variation in optly_experiment.variations_map.values():
+            self.assertIsInstance(variation, optimizely_config.OptimizelyVariation)
+            if variation.id == '10418551353':
+                self.assertEqual(variation.key, 'all_traffic_variation')
+            else:
+                self.assertEqual(variation.key, 'no_traffic_variation')