BentoSdk Subscribers API
Mix.install([
{:bento_sdk, "~> 0.1.0"}
])
Introduction
This notebook demonstrates how to use the BentoSdk to work with subscribers in the Bento marketing platform. The Subscribers API allows you to:
- Find subscribers
- Create subscribers
- Find or create subscribers (upsert)
- Import subscribers in bulk
- Change subscriber email
- Subscribe/unsubscribe users
Configuration
We’ll use Livebook’s secrets feature to securely store and access your Bento credentials:
# Configure BentoSdk with the LiveBook secrets
BentoSdk.configure(
site_uuid: System.fetch_env!("LB_BENTO_SITE_UUID"),
username: System.fetch_env!("LB_BENTO_USERNAME"),
password: System.fetch_env!("LB_BENTO_PASSWORD")
)
Finding Subscribers
Let’s find a subscriber by email:
# Example of finding a subscriber
email = "user@example.com"
case BentoSdk.Subscribers.find(email) do
{:ok, nil} ->
"Subscriber not found"
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Creating Subscribers
Now let’s create a new subscriber:
# Example of creating a subscriber
email = "new_user@example.com"
case BentoSdk.Subscribers.create(email) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Finding or Creating Subscribers (Upsert)
This is a common operation that will find a subscriber if they exist, or create them if they don’t:
# Example of finding or creating a subscriber
email = "user@example.com"
case BentoSdk.Subscribers.find_or_create(email) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Importing Subscribers in Bulk
You can import multiple subscribers at once:
# Example of importing subscribers in bulk
subscribers = [
%{
email: "user1@example.com",
first_name: "User",
last_name: "One"
},
%{
email: "user2@example.com",
first_name: "User",
last_name: "Two"
}
]
case BentoSdk.Subscribers.import(subscribers) do
{:ok, result} ->
result
{:error, reason} ->
"Error: #{reason}"
end
Changing Subscriber Email
You can change a subscriber’s email address:
# Example of changing a subscriber's email
old_email = "old_email@example.com"
new_email = "new_email@example.com"
case BentoSdk.Subscribers.change_email(old_email, new_email) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Updating Subscriber Attributes
You can update a subscriber’s attributes:
# Example of updating a subscriber's attributes
email = "user@example.com"
attributes = %{first_name: "Alan", last_name: "Bradburne"}
case BentoSdk.Subscribers.update(email, attributes) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Subscribe/Unsubscribe
You can subscribe or unsubscribe users:
# Example of subscribing a user
email = "user@example.com"
case BentoSdk.Subscribers.subscribe(email) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
# Example of unsubscribing a user
email = "user@example.com"
case BentoSdk.Subscribers.unsubscribe(email) do
{:ok, subscriber} ->
subscriber
{:error, reason} ->
"Error: #{reason}"
end
Example: Creating a Newsletter Signup Flow
Here’s an example of how you might handle a newsletter signup:
# Example of a newsletter signup flow
email = "newsletter_signup@example.com"
# First, check if the subscriber already exists
subscriber_result = BentoSdk.Subscribers.find(email)
case subscriber_result do
{:ok, nil} ->
# Subscriber doesn't exist, create a new one
case BentoSdk.Subscribers.create(email) do
{:ok, subscriber} ->
%{
status: "success",
message: "Thank you for subscribing to our newsletter!",
subscriber: subscriber
}
{:error, reason} ->
%{
status: "error",
message: "Failed to create subscriber: #{reason}"
}
end
{:ok, existing_subscriber} ->
# Subscriber exists, update their tags
# Get existing tags
cached_tag_ids = existing_subscriber["attributes"]["cached_tag_ids"] || []
{:ok, tags} = BentoSdk.Tags.get()
existing_tags = Enum.map(cached_tag_ids, fn tag_id ->
tags |> Enum.find(fn tag -> tag["id"] == tag_id end) |> Map.get("attributes") |> Map.get("name")
end)
new_tags = ["newsletter", "website_signup"] -- existing_tags
if Enum.empty?(new_tags) do
%{
status: "success",
message: "You are already subscribed to our newsletter.",
subscriber: existing_subscriber
}
else
# Add the new tags
case BentoSdk.Subscribers.add_tags(email, new_tags) do
{:ok, updated_subscriber} ->
%{
status: "success",
message: "Your newsletter preferences have been updated.",
subscriber: updated_subscriber
}
{:error, reason} ->
%{
status: "error",
message: "Failed to update tags: #{reason}"
}
end
end
{:error, reason} ->
%{
status: "error",
message: "Failed to check subscriber: #{reason}"
}
end
Example: Bulk Import with Error Handling
Here’s an example of how you might handle a bulk import with error handling:
# Example of bulk import with error handling
subscribers = [
%{
email: "valid_user@example.com",
first_name: "Valid",
last_name: "User"
},
%{
email: "invalid-email", # Invalid email format
first_name: "Invalid",
last_name: "User"
},
%{
email: "duplicate@example.com",
first_name: "Duplicate",
last_name: "User"
},
%{
email: "duplicate@example.com", # Duplicate email
first_name: "Another",
last_name: "Duplicate"
}
]
# Validate emails before import
validated_subscribers = Enum.filter(subscribers, fn subscriber ->
email = subscriber.email
# Simple regex for email validation
email_regex = ~r/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
Regex.match?(email_regex, email)
end)
# Remove duplicates by email
unique_subscribers = Enum.uniq_by(validated_subscribers, & &1.email)
# Import the validated and deduplicated subscribers
case BentoSdk.Subscribers.import(unique_subscribers) do
{:ok, result} ->
%{
status: "success",
total_attempted: length(subscribers),
total_valid: length(validated_subscribers),
total_unique: length(unique_subscribers),
total_imported: result["imported"] || 0,
invalid_count: length(subscribers) - length(validated_subscribers),
duplicate_count: length(validated_subscribers) - length(unique_subscribers),
import_result: result
}
{:error, reason} ->
%{
status: "error",
message: "Import failed: #{reason}",
total_attempted: length(subscribers)
}
end