Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@
3.2.0 (Feb 2, 2025)
- Updated to support flag sets, large segments and the impressionsDisabled boolean value
3.5.0 (May 6, 2025)
- Updated to support harness mode
- Updated to support harness mode
3.5.1 (June 20, 2025)
- Updated to support rule based segments
208 changes: 208 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,214 @@ definition= {"treatments":[ {"name":"on"},{"name":"off"}],
splitDef.submit_change_request(definition, 'UPDATE', 'updating default rule', 'comment', ['user@email.com'], '')
```

### Rule-Based Segments

Rule-based segments allow you to define audience segments using complex rule structures and exclusion logic. Added in version 3.5.1, they offer enhanced functionality for targeting users.

Fetch all Rule-Based Segments:

```python
ws = client.workspaces.find("Defaults")
for segment in client.rule_based_segments.list(ws.id):
print("\nRule-Based Segment: " + segment.name + ", " + segment.description)
```

Add new Rule-Based Segment:

```python
segment_data = {
'name': 'advanced_users',
'description': 'Users who match advanced criteria'
}
rule_segment = ws.add_rule_based_segment(segment_data, "user")
print(rule_segment.name)
```

Add Rule-Based Segment to environment:

```python
ws = client.workspaces.find("Defaults")
segment = client.rule_based_segments.find("advanced_users", ws.id)
env = client.environments.find("Production", ws.id)
segdef = segment.add_to_environment(env.id)
```

#### Rule-Based Segment Structure

Rule-based segment definitions support multiple rule types and matching conditions:

```python
# Examples of different matcher types
matchers = [
# String matching
{
'type': 'IN_LIST_STRING',
'attribute': 'device',
'strings': ['mobile', 'tablet']
},
# Numeric comparisons
{
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
'attribute': 'age',
'number': 21
},
{
'type': 'LESS_THAN_OR_EQUAL_NUMBER',
'attribute': 'account_age_days',
'number': 30
},
{
'type': 'BETWEEN_NUMBER',
'attribute': 'purchases',
'between': {'from': 5, 'to': 20}
},
# Boolean conditions
{
'type': 'BOOLEAN',
'attribute': 'subscribed',
'bool': True
},
# Date/time matching
{
'type': 'ON_DATE',
'attribute': 'sign_up_date',
'date': 1623456789000 # timestamp in milliseconds
},
# Dependency on another split
{
'type': 'IN_SPLIT',
'attribute': '',
'depends': {'splitName': 'another_split', 'treatment': 'on'}
}
]

# Multiple conditions using combiners
condition = {
'combiner': 'AND', # Can only be 'AND'
'matchers': matchers
}
```

Update Rule-Based Segment definition with rules:

```python
ws = client.workspaces.find("Defaults")
env = client.environments.find("Production", ws.id)
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)

# Define rules that match users in a certain list
rules_data = {
'rules': [
{
'condition': {
'combiner': 'AND',
'matchers': [
{
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
'attribute': 'age',
'number': 30
},
{
'type': 'BOOLEAN',
'attribute': 'completed_tutorials',
'bool': True
}
]
}
}
]
}

# Update the segment definition with the rules
updated_segdef = segdef.update(rules_data)
```

Update Rule-Based Segment definition with excluded keys and excluded segments:

```python
ws = client.workspaces.find("Defaults")
env = client.environments.find("Production", ws.id)
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)

# Define rules and exclusion data
update_data = {
'rules': [
{
'condition': {
'combiner': 'AND',
'matchers': [
{
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
'attribute': 'age',
'number': 30
}
]
}
}
],
'excludedKeys': ['user1', 'user2', 'user3'],
'excludedSegments': [
{
'name': 'beta_testers',
'type': 'standard_segment'
}
]
}

# Update the segment definition with rules and exclusions
updated_segdef = segdef.update(update_data)
```

Submit a Change request to update a Rule-Based Segment definition:

```python
ws = client.workspaces.find("Defaults")
env = client.environments.find("Production", ws.id)
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)

# New rules for the change request
rules = [
{
'condition': {
'combiner': 'AND',
'matchers': [
{
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
'attribute': 'age',
'number': 25
},
{
'type': 'BOOLEAN',
'attribute': 'completed_tutorials',
'bool': True
}
]
}
}
]

# Define excluded keys and segments for the change request
excluded_keys = ['user1', 'user2']
excluded_segments = [
{
'name': 'test_users',
'type': 'rule_based_segment'
}
]

# Submit change request with all parameters
segdef.submit_change_request(
rules=rules,
excluded_keys=excluded_keys,
excluded_segments=excluded_segments,
operation_type='UPDATE',
title='Lower age threshold to 25',
comment='Including more users in advanced segment',
approvers=['user@email.com'],
workspace_id=ws.id
)
```

List all change requests:

```python
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "splitapiclient"
version = "3.5.0"
version = "3.5.1"
description = "This Python Library provide full support for Split REST Admin API, allow creating, deleting and editing Environments, Splits, Split Definitions, Segments, Segment Keys, Users, Groups, API Keys, Change Requests, Attributes and Identities"
classifiers = [
"Programming Language :: Python :: 3",
Expand Down
8 changes: 8 additions & 0 deletions splitapiclient/main/apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ def segments(self):
@abc.abstractproperty
def segment_definitions(self):
pass

@abc.abstractproperty
def rule_based_segments(self):
pass

@abc.abstractproperty
def rule_based_segment_definitions(self):
pass

@abc.abstractproperty
def workspaces(self):
Expand Down
12 changes: 12 additions & 0 deletions splitapiclient/main/sync_apiclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from splitapiclient.microclients import SplitDefinitionMicroClient
from splitapiclient.microclients import SegmentMicroClient
from splitapiclient.microclients import SegmentDefinitionMicroClient
from splitapiclient.microclients import RuleBasedSegmentMicroClient
from splitapiclient.microclients import RuleBasedSegmentDefinitionMicroClient
from splitapiclient.microclients import WorkspaceMicroClient
from splitapiclient.microclients import IdentityMicroClient
from splitapiclient.microclients import AttributeMicroClient
Expand Down Expand Up @@ -67,6 +69,8 @@ def __init__(self, config):
self._split_definition_client = SplitDefinitionMicroClient(http_client)
self._segment_client = SegmentMicroClient(http_client)
self._segment_definition_client = SegmentDefinitionMicroClient(http_client)
self._rule_based_segment_client = RuleBasedSegmentMicroClient(http_client)
self._rule_based_segment_definition_client = RuleBasedSegmentDefinitionMicroClient(http_client)
self._large_segment_client = LargeSegmentMicroClient(http_client)
self._large_segment_definition_client = LargeSegmentDefinitionMicroClient(http_client)
self._workspace_client = WorkspaceMicroClient(http_client)
Expand Down Expand Up @@ -103,6 +107,14 @@ def segments(self):
@property
def segment_definitions(self):
return self._segment_definition_client

@property
def rule_based_segments(self):
return self._rule_based_segment_client

@property
def rule_based_segment_definitions(self):
return self._rule_based_segment_definition_client

@property
def large_segments(self):
Expand Down
4 changes: 3 additions & 1 deletion splitapiclient/microclients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
from splitapiclient.microclients.restriction_microclient import RestrictionMicroClient
from splitapiclient.microclients.flag_set_microclient import FlagSetMicroClient
from splitapiclient.microclients.large_segment_microclient import LargeSegmentMicroClient
from splitapiclient.microclients.large_segment_definition_microclient import LargeSegmentDefinitionMicroClient
from splitapiclient.microclients.large_segment_definition_microclient import LargeSegmentDefinitionMicroClient
from splitapiclient.microclients.rule_based_segment_microclient import RuleBasedSegmentMicroClient
from splitapiclient.microclients.rule_based_segment_definition_microclient import RuleBasedSegmentDefinitionMicroClient
Loading