The BlueConic Python package is the cornerstone of building custom notebooks in AI Workbench. Using it will open up endless possibilities to analyze and optimize your BlueConic profile data.
See the BlueConic Python API documentation site for details on developing applications for AI Workbench with the Python API. Also, developers should note the list of Python dependencies that are published on that site.
Python code snippet 1: Set up a basic 'get_profiles' loop
This first code snippet implements a basic loop to process BlueConic profiles. Using the count
parameter of the get_profiles
method makes sure that only the first 5,000 profiles of the "All visitors" segment are processed. Processing all profiles in this segment could potentially take a very long time to execute.
# Import the BlueConic client import blueconic bc = blueconic.Client() # Counter to keep track of the profiles with one or more email addresses nr_profiles = 0 # Loop over first 5,000 profiles in the "All Visitors" segment for profile in bc.get_profiles(segment_id="allvisitors", count=5000): # Retrieve the value of the "email" profile property email_address = profile.get_value("email") # When there is a value present for the email address, increase the counter if email_address: nr_profiles += 1 if nr_profiles <= 10: print(f"Email address {nr_profiles}: {email_address}") # Print the result print(f"Profiles with an email address: {nr_profiles}")
Python code snippet 2: Only retrieve profiles with an Email Address and only ask for the Email Address property
The second code snippet resolves a few issues from example 1:
- In the first snippet, all the data in each profile is returned, including data we don't need for our notebook. In this example, we add the
properties
parameter to theget_profiles
method so only the values for the listed properties (in this case the "email" property) are returned. - In the first code snippet, the first 5,000 profiles of the "All visitors" segment are returned, including profiles that have no value for the profile property that we want to analyze. By using the
required_properties
parameter for theget_profiles
method, profiles are returned only if they have one or more values for the listed profile properties (in our example, profiles with values for a property with the id "email"). - In the first snippet, the count was set to 5,000 to prevent a long execution time. Now that we've made sure that only relevant profiles are returned (by using the
required_properties
parameter), we set the count to zero (0), which means that all profiles will be returned that are part of the segment with the id "allvisitors" and have a value for the profile property with the id "email". Note: This could still lead to long execution times when you have a lot of profiles with a value for the listedrequired_properties
.
# Import the BlueConic client import blueconic bc = blueconic.Client() # Counter to keep track of the profiles with one or more email addresses nr_profiles = 0 # Loop over all profiles in the "All Visitors" segment where there is # a value present for the "email" profile property. # Also only return the "email" property for each profile. for profile in bc.get_profiles(segment_id="allvisitors", required_properties=["email"], properties=["email"], count=0): # Increase the 'number of profiles with one or more values' counter nr_profiles += 1 # Print the result print(f"Profiles with an email address: {nr_profiles}")
Python code snippet 3: Enrich profiles using the profile bulk handler
Code snippet 2 loops over all profiles that have one or more email addresses. In this example, the number of email addresses within a profile is written back to a new profile property (with the id "nr_email_addresses") in the same profile. Profiles can only be updated by using the profile bulk handler.
Note: This example requires that you have a BlueConic profile property with the id "nr_email_addresses". Create this profile property before running the code example.
# Import the BlueConic client import blueconic bc = blueconic.Client() # Counter to keep track of the profiles with one or more email addresses nr_profiles = 0 # Retrieve the profile bulk handler to update profiles in bulk with bc.get_profile_bulkhandler() as pbh: # Loop over all profiles in the "All Visitors" segment where there is # a value present for the "email" profile property. # Also only return the "email" property for each profile. for profile in bc.get_profiles(segment_id="allvisitors", properties=["email"], required_properties=["email"], count=0): # Retrieve the number of values in "email" profile property nr_email_addresses = len(profile.get_values("email")) # Write the number of email addresses to the "nr_email_addresses" property profile.set_value("nr_email_addresses", nr_email_addresses) # Write the updated profile back to BlueConic pbh.write(profile) # Increase the 'number of profiles with one or more values' counter nr_profiles += 1 # Print the result print(f"Updated {nr_profiles} profiles")
Python code snippet 4: Use the Parameters feature to retrieve the segment and profile properties
In snippet 3, the ids of the BlueConic items that are needed are placed in the source code of the notebook (for example: the profile property id "email" that refers to the "Email Address" profile property). This is not ideal because sometimes as a developer you won't know the id of a needed item.
Using the Parameters feature of the BlueConic AI Workbench solves this issue. Here's how it works:
- In the source code, retrieve the value for a parameter of a certain type, using the
get_blueconic_parameter_value
orget_blueconic_parameter_values
method. - All parameters from the notebook code are automatically listed in the left navigation menu of the AI Workbench "Parameters" tab.
- Marketers can enter a value for each parameter using the UI.
- When you run the notebook code, the value(s) marketers enter for the parameters are inserted into the notebook.
# Import the BlueConic client import blueconic bc = blueconic.Client() # "segment" parameter: The segment to process the profiles from source_segment_id = bc.get_blueconic_parameter_value(
"Segment to process","segment"
) # "profile_property" parameter: Count the number of values this
# profile property contains source_property_id = bc.get_blueconic_parameter_value(
"Source Property", "profile_property"
) # "profile_property" parameter: Store the value count of source_property_id
# into this property target_property_id = bc.get_blueconic_parameter_value("Target Property",
"profile_property") # Counter to keep track of the profiles with one or more values nr_profiles = 0 # Retrieve the profile bulk handler to update profiles in bulk with bc.get_profile_bulkhandler() as pbh: # Loop over all profiles in source_segment_id where there is
a value present in source_property_id for profile in bc.get_profiles(segment_id=source_segment_id, properties=[source_property_id], required_properties=[source_property_id], count=0): # Retrieve the number of values of the source_property_id nr_email_addresses = len(profile.get_values(source_property_id)) # Write the number of values present in source_property_id to
# target_property_id profile.set_value(target_property_id, nr_email_addresses) # Write the updated profile back to BlueConic pbh.write(profile) # Increase the 'number of profiles with one or more values' counter nr_profiles += 1 # Print the result print(f"Updated {nr_profiles} profiles")
Python code snippet 5: Update only the profiles that have changed values since the last run
Snippet 4 produces the correct results, but can be further optimized for performance. Once we have determined the number of values in a profile property (and wrote the result back to another property in the same profile), this notebook doesn't have to analyze a profile again if it has not been changed since the last successful run of this notebook, or if the value for the Number of Email Addresses profile property didn't change.
To make this happen, we add the following changes to snippet 4:
- Add a fourth profile property parameter that contains the moment of the last update to the profile.
- Create a function that returns the date of the last successful execution of this notebook.
- Create a filter that will leave out all profiles that have not been updated since the last successful execution of this notebook.
- Apply the filter through the
filters
parameter when retrieving profiles with theget_profiles
method. - Let
get_profiles
also return the value for the Number of Email Addresses profile property, and use this value to implement a check so only profiles are updated that have a changed value for this property.
# Import the BlueConic client import blueconic bc = blueconic.Client() # "segment" parameter: The segment to process the profiles from source_segment_id = bc.get_blueconic_parameter_value(
"Segment to process","segment"
) # "profile_property" parameter: Count the number of values this profile
property contains source_property_id = bc.get_blueconic_parameter_value("Source Property",
"profile_property") # "profile_property" parameter: Store the value count of source_property_id
into this property target_property_id = bc.get_blueconic_parameter_value("Target Property",
"profile_property") # "profile_property" parameter: Last modified date of the profile source_last_modified_date =
bc.get_blueconic_parameter_value("Last mod. date", "profile_property") # Returns the start date of the last successful execution of this notebook def get_last_successful_execution_start_date(): for execution in bc.get_executions(count=10): if execution.state == "FINISHED": return execution.start_date return None # Use the last successful execution of this notebook to add a filter based # on the "lastmodifieddate" profile property. This filter will make sure # that only profiles that have been updated since the last successful run # will be processed again by this notebook. all_filters = [] last_successful_execution_start_date = get_last_successful_execution_start_date() if last_successful_execution_start_date: lastmodified_date_filter =
blueconic.get_filter(source_last_modified_date).in_range(
min=last_successful_execution_start_date
) all_filters = [lastmodified_date_filter] # Counter to keep track of the profiles with one or more values nr_profiles = 0 # Retrieve the profile bulk handler to update profiles in bulk with bc.get_profile_bulkhandler() as pbh: # Loop over all profiles in source_segment_id where there
is a value present in source_property_id for profile in bc.get_profiles(segment_id=source_segment_id, properties=[source_property_id,
target_property_id], required_properties=[source_property_id], count=0, filters=all_filters): # Retrieve the number of values of the source_property_id nr_email_addresses = len(profile.get_values(source_property_id)) # Check if the number of values in the property has changed if nr_email_addresses != profile.get_value(target_property_id): # Write the number of values present in source_property_id
to target_property_id profile.set_value(target_property_id, nr_email_addresses) # Write the updated profile back to BlueConic pbh.write(profile) # Increase 'number of profiles with one or more values' counter nr_profiles += 1 # Print the result print(f"Updated {nr_profiles} profiles")
Python dependencies
For a list of current Python dependencies for developers creating Jupyter notebooks in the BlueConic AI Workbench, see https://supportdocs.blueconic.com/python/changelog/100-dependencies-changelog.html.