Working with Kentico Contacts in Third-Party Systems

Working with Kentico Contacts in Third-Party Systems

Mar 22, 2018
Working with Kentico Contacts in Third-Party Systems

While Kentico EMS offers an excellent feature set for working with contacts, I am often asked to integrate it into third-party systems and keep contact information in sync between them. Frequently, these integrations are for mailing systems such as MailChimp or ConstantContact.

Before I get into the solution, I’d first like to say that Kentico offers a great mailing list management solution of its own in the Email Marketing module. In Kentico 11, they even have a user-friendly drag and drop email builder.

If you have set up your SMTP servers correctly using a service such as SendGrid or MailGun, the built-in solutions are just as good, if not better than many third-party mailing list managers. Integrating with third-party systems will cost you more money both up front and in the long term as you will have to maintain the integration as and when the third parties update their APIs. For that reason, every Kentico admin should first consider using the built-in tools for this rather than integrating with a third party.

That said, when I am forced to integrate…

Here’s How I Do It…

Requirements and Required Reading

Firstly, you must ensure that you have somewhere in your third-party system to store the Kentico ContactID for each contact. This is how you will identify the contact in some cases.

Using Kentico’s global events, I can capture the “insert” and “update” events for the contacts. If you are unfamiliar with Kentico global events, I recommend the following links as required reading:

Global Events

The events you will need to handle are registered in your module’s OnInit() method like so:

{^widget|(language)csharp|(showlinenumbers)True|(name)SyntaxHighlighter|(code)1.%09ContactInfo.TYPEINFO.Events.Insert.After+%2b%3d+HandleContactInsertUpdate%3b++%0d%0a2.%09ContactInfo.TYPEINFO.Events.Update.After+%2b%3d+HandleContactInsertUpdate%3b++%0d%0a3.%09ContactInfo.TYPEINFO.Events.Delete.After+%2b%3d+HandleContactDelete%3b++%0d%0a4.%09ContactManagementEvents.ContactInfosDeleted.Execute+%2b%3d+HandleMultipleContactsDeleted%3b++%0d%0a5.%09DataProtectionEvents.RevokeConsentAgreement.Execute+%2b%3d+HandleRevokeConsent%3b|(autolinks)False|(image_guid)c204d924-ab74-43bb-817c-5ceba8617ee3|(showcollapsed)False|(widget_displayname)Syntax+highlighter|(width)|(height)^}

The above event-handlers cover all scenarios where you would need to take action in your third-party system in relation to a Contact from Kentico.

Handling the Events

Insert and Update are going to perform the same functionality so can use the same method:

{^widget|(language)csharp|(showlinenumbers)True|(name)SyntaxHighlighter|(code)1.%09private+void+HandleContactInsertUpdate(object+sender%2c+ObjectEventArgs+e)++%0d%0a2.%09%7b++%0d%0a3.%09++++var+contact+%3d+e.Object+as+ContactInfo%3b++%0d%0a4.%09++%0d%0a5.%09++++%2f%2f+If+the+objec+tisn%27t+a+contact+return+out.++%0d%0a6.%09++++if+(contact+%3d%3d+null)+return%3b++%0d%0a7.%09++%0d%0a8.%09++++%2f%2f+Prevent+recursion++%0d%0a9.%09++++if+(e.DetectRecursion(%24%22ContactInsertUpdate-%7bcontact.ContactID%7d%22))+return%3b++%0d%0a10.%09++%0d%0a11.%09++++%2f%2f+If+the+contact+doesn%27t+have+the+fields+we+need+currently%2c+return+out.++%0d%0a12.%09++++if+(string.IsNullOrWhiteSpace(contact.ContactEmail)+%7c%7c++%0d%0a13.%09++++string.IsNullOrWhiteSpace(contact.ContactFirstName)+%7c%7c++%0d%0a14.%09++++string.IsNullOrWhiteSpace(contact.ContactLastName))++%0d%0a15.%09++++++++return%3b++%0d%0a16.%09++%0d%0a17.%09++++%2f*+%0d%0a18.%09++++++++*+If+we%27re+in+Kentico+11+we+also+need+to+check+for+consent.+%0d%0a19.%09++++++++*++%0d%0a20.%09++++++++*+If+you%27re+in+an+older+version+of+Kentico+you+can+ignore+the+consent-related+%0d%0a21.%09++++++++*+code+below+but+will+likely+have+to+implement+your+own+consent+methods+to+%0d%0a22.%09++++++++*+comply+with+GDPR.+%0d%0a23.%09++++++++*%2f++%0d%0a24.%09++%0d%0a25.%09++++%2f%2f+Get+the+consent+-+replace+the+%22ThirdPartySystemConsentName%22+with+the+name+of+the+relevant+Consent+in+your+site++%0d%0a26.%09++++ConsentInfo+consent+%3d+ConsentInfoProvider.GetConsentInfo(%22ThirdPartySystemConsentName%22)%3b++%0d%0a27.%09++%0d%0a28.%09++++%2f%2f+Initializes+an+instance+of+the+consent+agreement+service++%0d%0a29.%09++++IConsentAgreementService+consentAgreementService+%3d+Service.Resolve%3cIConsentAgreementService%3e()%3b++%0d%0a30.%09++%0d%0a31.%09++++%2f%2f+Checks+if+the+contact+has+given+an+agreement+with+the+consent++%0d%0a32.%09++++bool+agreed+%3d+consentAgreementService.IsAgreed(contact%2c+consent)%3b++%0d%0a33.%09++%0d%0a34.%09++++if+(agreed)++%0d%0a35.%09++++%7b++%0d%0a36.%09++++++++%2f%2f+Do+your+work+to+insert%2fupdate+the+contact+in+the+third-party+system.++%0d%0a37.%09++++%7d++%0d%0a38.%09++++else++%0d%0a39.%09++++%7b++%0d%0a40.%09++++++++%2f%2f+Check+the+third-party+system+for+the+existence+of+this+contact+and+delete+them+from+there.+Use+the+contacts+email+address+and+remove+all+references+to+it+in+your+third-party+system++++%0d%0a41.%09++++%7d++%0d%0a42.%09%7d|(autolinks)False|(image_guid)c204d924-ab74-43bb-817c-5ceba8617ee3|(showcollapsed)False|(widget_displayname)Syntax+highlighter|(width)|(height)^}

If you’re using Kentico 11 then you also need to handle the event when a contact revokes their consent:

{^widget|(language)csharp|(showlinenumbers)True|(name)SyntaxHighlighter|(code)1.%09private+void+HandleRevokeConsent(object+sender%2c+RevokeConsentAgreementEventArgs+e)++%0d%0a2.%09%7b++%0d%0a3.%09++++var+contact+%3d+e.Contact%3b++%0d%0a4.%09++++var+consent+%3d+e.Consent%3b++%0d%0a5.%09++%0d%0a6.%09++++%2f%2f+replace+the+%22ThirdPartySystemConsentName%22+with+the+name+of+the+relevant+Consent+in+your+site++%0d%0a7.%09++++if+(consent.ConsentName+!%3d+%22ThirdPartySystemConsentName%22)+return%3b++%0d%0a8.%09++%0d%0a9.%09++++%2f%2f+now+delete+the+contact+from+your+third-party+system+here.+Use+the+contacts+email+address+and+remove+all+references+to+it+in+your+third-party+system++%0d%0a10.%09%7d|(autolinks)False|(image_guid)c204d924-ab74-43bb-817c-5ceba8617ee3|(showcollapsed)False|(widget_displayname)Syntax+highlighter|(width)|(height)^}

When a single contact is deleted, we need to handle it and delete it from the third-party system:

{^widget|(language)csharp|(showlinenumbers)True|(name)SyntaxHighlighter|(code)1.%09private+void+HandleContactDelete(object+sender%2c+ObjectEventArgs+e)++%0d%0a2.%09%7b++%0d%0a3.%09++++var+contact+%3d+e.Object+as+ContactInfo%3b++%0d%0a4.%09++%0d%0a5.%09++++%2f%2f+If+the+objec+tisn%27t+a+contact+return+out.++%0d%0a6.%09++++if+(contact+%3d%3d+null)+return%3b++%0d%0a7.%09++%0d%0a8.%09++++%2f%2f+Prevent+recursion++%0d%0a9.%09++++if+(e.DetectRecursion(%24%22ContactDelete-%7bcontact.ContactID%7d%22))+return%3b++%0d%0a10.%09++%0d%0a11.%09++++%2f%2f+now+delete+the+contact+from+your+third-party+system+here.+Use+the+contacts+email+address+and+remove+all+references+to+it+in+your+third-party+system++++%0d%0a12.%09%7d|(autolinks)False|(image_guid)c204d924-ab74-43bb-817c-5ceba8617ee3|(showcollapsed)False|(widget_displayname)Syntax+highlighter|(width)|(height)^}

Finally, if multiple contacts are deleted at the same time, Kentico calls a different event:

{^widget|(language)csharp|(showlinenumbers)True|(name)SyntaxHighlighter|(code)1.%09private+void+HandleMultipleContactsDeleted(object+sender%2c+ContactInfosDeletedHandlerEventArgs+e)++%0d%0a2.%09%7b++%0d%0a3.%09++++var+contacts+%3d+e.DeletedContactsIds%3b++%0d%0a4.%09++%0d%0a5.%09++++%2f%2f+Note+that+we+only+have+the+contact+ID%27s+here.++You+must+ensure+that+your+third-party+system+stores+the+ContactID+from+Kentico+in+some+way.++%0d%0a6.%09++++%2f%2f+In+most+third-party+mailing+list+systems+you+can+add+it+as+a+merge+field+to+the+recipient.++%0d%0a7.%09++++++++++++++%0d%0a8.%09++++%2f%2f+now+delete+the+contact+from+your+third-party+system+here.++%0d%0a9.%09%7d+|(autolinks)False|(image_guid)c204d924-ab74-43bb-817c-5ceba8617ee3|(showcollapsed)False|(widget_displayname)Syntax+highlighter|(width)|(height)^}

In Summary

The solution given above ensures that contacts are kept in sync with third-party systems while also honoring the Kentico 11 consent system. It could easily be adapted for use in Kentico 9 or 10 with minimal work, but if you are considering this level of integration relating to contacts, then I would highly recommend upgrading to Kentico 11 to make use of the GDPR module and consents.