Skip to content

[Dotdigital] Add actions for Add Contact to List, Remove Contact From List, and Enrol Contact #2871

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

pvpcookie
Copy link

What's New
We have added three new actions as part of the initial release for the Dotdigital action destination in Segment IO:

  • Remove Contact from List
    This action is used to remove a contact from a list they were previously subscribed to.

  • Enroll Contact
    This action is used to enroll a contact into an automation program in Dotdigital.

  • Add Contact to List
    This action is intended to add or update a contact in Dotdigital.

Why This Was Changed / Added
We are expanding the scope of available actions for the Dotdigital platform.


How to Review / Test This Change
Run the following commands:

yarn eslint packages/destination-actions/src/destinations/dotdigital/
yarn cloud test --testPathPattern=packages/destination-actions/src/destinations/dotdigital

@pvpcookie pvpcookie requested a review from a team as a code owner April 15, 2025 12:26
@pvpcookie pvpcookie changed the title Release 1.0.0 [Dotdigital] Add actions for Add Contact to List, Remove Contact From List, and Enrol Contact Apr 15, 2025
@joe-ayoub-segment joe-ayoub-segment self-assigned this May 5, 2025
@joe-ayoub-segment
Copy link
Contributor

Hi @pvpcookie thanks for the PR for a new Integration!
qq - have you registered Dot Digital as a Segment Partner yet?
I'll review this PR in the next 24h.

Kind regards,
Joe

import addContactToList from './addContactToList'
const destination: DestinationDefinition<Settings> = {
name: 'Dotdigital',
slug: 'actions-dotdigital',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a 1 line description explaining what the Integration does.

password: {
label: 'Password',
description: 'Your Dotdigital password.',
type: 'string',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type: 'string',
type: 'password',

label: 'Email Address',
description: "The contact's email address.",
type: 'string',
unsafe_hidden: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @pvpcookie are you aware that this field will be hidden from the user regardless of whether or not the customer selects email as the Channel Identifier?
I think you should remove the unsafe_hidden: true line. The field will display if the depends_on condition is met.

label: 'Mobile Number',
description: "The contact's mobile number.",
type: 'string',
unsafe_hidden: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should remove the unsafe_hidden: true line. The field will display if the depends_on condition is met.

Comment on lines +47 to +49
if (!listId) {
throw new PayloadValidationError('List id is required')
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Probably not needed. Payloads without a listId value will get dropped before the perform() function is called.

Comment on lines +51 to +55
if (!identifierValue) {
throw new PayloadValidationError(
channelIdentifier === 'email' ? 'Email address is required' : 'Mobile number is required'
)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same with this - there should always be an identifierValue as email the email or mobile fields will be populated. So this check probably not needed.

Comment on lines +25 to +27
defaultObjectUI: 'keyvalue:only',
additionalProperties: false,
dynamic: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @pvpcookie - I think there's some conflicting configuration here.

defaultObjectUI: 'keyvalue:only' - this means that the UI will only let the customer configure key:value pairs in the object, rather than passing the entire object in a single go.

additionalProperties: false - this will prevent the customer from adding new key:value items.

The net result of this is that only a single key:value pair will be configurable - that is assuming the UI will actually implement the config as expected.

I think this the following is what you actually want:

  • allow the customer to add many key:value pairs to the dataFields object, one at a time. Each time the customer selects to add a new item the dynamic function will be called and will populate the list of keys the customer can select from.

To achieve this I think you chould remove the additionalProperties: false configuration.

const action: ActionDefinition<Settings, Payload> = {
title: 'Add Contact to List',
description: '',
defaultSubscription: 'type = "identify"',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth considering if an identify() call is the best way to do this. I would recommend a defaultSubscription that looks for a track() event. For example:

defaultSubscription: 'type = "track" and event="Added To List"',

const action: ActionDefinition<Settings, Payload> = {
title: 'Remove Contact from List',
description: '',
defaultSubscription: 'type = "identify"',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth considering if an identify() call is the best way to do this. I would recommend a defaultSubscription that looks for a track() event. For example:

defaultSubscription: 'type = "track" and event="Removed From List"',

@joe-ayoub-segment
Copy link
Contributor

hi @pvpcookie and @simon-letch thanks for the PR.

I reviewed what I could but I have some architectural questions I'd like to discuss with you in person, just to ensure that this Integration is designed in an optimal way.

Would it be possible to schedule a call with me? I'm based in Ireland - I see that you are both based in the UK and SA so our timezones overlap well.

The main things I'd like to discuss are:

  1. Do you want customers to be able to sync a Segment / Engage Audience to your Lists?
  2. Do you want to allow Segment to create (upsert) a new List on your platform - before a Contact is added to the list?
  3. Should we use a single Action for adding/removing contacts from a List?
  4. Default mappings: I think these should be track() events. I'll explain more when we meet
  5. Coding style is fairly verbose - I think we could simplify it.

Please reply in this PR with 2-3 times which would work for us to connect on Tuesday or Wednesday this week. Usually this type of discussion needs about 1h. We can have a follow up too if needed.

Kind regards,
Joe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants