Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Add support for deduplicating events with event IDs #107

Open
marckohlbrugge opened this issue Sep 22, 2023 · 0 comments

Comments

@marckohlbrugge
Copy link

marckohlbrugge commented Sep 22, 2023

From the documentation

From https://customer.io/docs/journeys/events/#deduplicating-events

You can provide an id with your events, to deduplicate events—if there’s a possibility that your integration might send duplicate events. The id must be a ULID. If two events contain the same id, we won’t process the event multiple times.

Deduplicating events helps you accurately represent people’s activity; can prevent people from accidentally entering or leaving campaigns based on the number of times that a person performed an event; and prevents duplicate events from impacting your workspace’s performance.

{
    "name": "my event",
    "id": "01BX5ZZKBKACTAV9WEVGEMMVRY",
    "data": {
        "prop1": "value"
    }
}

Relevant code

def create_customer_event(customer_id, event_name, attributes = {})
create_event(
url: "#{customer_path(customer_id)}/events",
event_name: event_name,
attributes: attributes
)
end

def create_event(url:, event_name:, anonymous_id: nil, event_type: nil, attributes: {})
body = { :name => event_name, :data => attributes }
body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
body[:anonymous_id] = anonymous_id unless is_empty?(anonymous_id)
body[:type] = event_type unless is_empty?(event_type)
@client.request_and_verify_response(:post, url, body)
end

def track(customer_id, event_name, attributes = {})
raise ParamError.new("customer_id must be a non-empty string") if is_empty?(customer_id)
raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
create_customer_event(customer_id, event_name, attributes)
end

Problem

As you can see, the expected JSON has a top-level id attribute. However, the existing code doesn't allow for this. Apart from a handful exceptions, it nests all attributes into a data object.

This means users of the gem currently don't have a way to provide an id to prevent duplicate events.

Proposed fix

Add an (optional) id parameter to create_event and all methods that reference it. Pass it as a top-level key to the API.

This will be a backwards-compatible change, as current implementations won't currently provide an id directly into the create_event calls. Notably, any id that might be included in the attributes hash continue to work as before.

def track(customer_id, event_name, attributes = {}) needs to be updated too. This is a bit trickier, because it uses positional arguments. I think adding a fourth, optional argument does the trick: def track(customer_id, event_name, attributes = {}, id = nil)

Optionally, the following code can be used to validate the correctness of the id:

def valid_ulid?(ulid)
  !!(ulid =~ /\A[0123456789ABCDEFGHJKMNPQRSTVWXYZabcdefghjkmnpqrstvwxyz]{26}\z/)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant