4
votes

I'm using Sitecore 8 and the new Email Experience Manager module. I have configured a newsletter email message with an empty list from the listmanager as recipients.

When subscribing for the newsletter via a selfmade form, I receive an email address and a name. Now I want to make a new contact with this mail and name and add it to the list in my listmanager via code.

Is there any way to call this list via the api and add a contact to it?

4

4 Answers

0
votes

I have had the exact same issue, i.e. the list manager reports 0 contacts after adding the contact to the recipient list.

I have investigated the issue closer and found that adding a contact to a recipient list actually just sets a field on the contact in the "sitecore_analytics_index" index (assuming you use Mongo/XDB as the underlying storage). Specifically, Sitecore should update the "contact.tags" field on the contact document with the value "ContactLists:{recipientListGuid}". I tried opening the index with Luke to verify that this field was indeed not being set in the index. The index is located in C:\inetpub\wwwroot[Sitename]\Data\indexes\sitecore_analytics_index.

This led me to the conclusion, that you have to save the contact after adding him to the recipient list.

Summing up, the following code works for me:

var ecm = EcmFactory.GetDefaultFactory();
XdbContactId contactId = /* some valid contact id */;
LeaseOwner leaseOwner = new LeaseOwner("UpdateContact-" + Guid.NewGuid().ToString(), LeaseOwnerType.OutOfRequestWorker);
Sitecore.Analytics.Tracking.Contact contact;
string webClusterName;
var status = ecm.Gateways.AnalyticsGateway.TryGetContactForUpdate(contactId.Value,
    leaseOwner,
    TimeSpan.FromSeconds(5),
     TimeSpan.FromSeconds(5),
     out contact, out webClusterName);

var recipientList = ecm.Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId);
  if (recipientList != null)
  {
    if (!recipientList.Contains(contactId, true).Value)
    {
      recipientList.AddRecipient(contactId);
    }
  }

contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
var contactRepository = new ContactRepository();
var success = contactRepository.SaveContact(contact, new ContactSaveOptions(true, leaseOwner));

Note, the above code is used in an update-scenario. In your case, I guess you just have to move this code:

contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));

After this:

var recipientList = EcmFactory.GetDefaultFactory().Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId);
  if (recipientList != null)
  {
    var xdbContact = new XdbContactId(contactId);
    if (!recipientList.Contains(xdbContact, true).Value)
    {
      recipientList.AddRecipient(xdbContact);
    }
  }

UPDATE: Actually the above only works if the contact saved is the contact currently tracked by Sitecore Analytics.

3
votes

To create a contact, you can use the sample code below, the contact name is usually the domain name plus the username, e.g. domain\username.

public static Contact CreateContact([NotNull] string contactName, [NotNull] string contactEmail, [NotNull] string contactLanguage)
{
  Assert.ArgumentNotNullOrEmpty(contactName, "contactName");
  Assert.ArgumentNotNullOrEmpty(contactEmail, "contactEmail");
  Assert.ArgumentNotNullOrEmpty(contactLanguage, "contactLanguage");

  var contactRepository = new ContactRepository();

  var contact = contactRepository.LoadContactReadOnly(contactName);
  if (contact != null)
  {
    return contact;
  }
  contact = contactRepository.CreateContact(ID.NewID);
  contact.Identifiers.AuthenticationLevel = AuthenticationLevel.None;
  contact.System.Classification = 0;
  contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
  contact.Identifiers.Identifier = contactName;
  contact.System.OverrideClassification = 0;
  contact.System.Value = 0;
  contact.System.VisitCount = 0;

  var contactPreferences = contact.GetFacet<IContactPreferences>("Preferences");
  contactPreferences.Language = contactLanguage;

  var contactEmailAddresses = contact.GetFacet<IContactEmailAddresses>("Emails");
  contactEmailAddresses.Entries.Create("test").SmtpAddress = contactEmail;
  contactEmailAddresses.Preferred = "test";

  var contactPersonalInfo = contact.GetFacet<IContactPersonalInfo>("Personal");
  contactPersonalInfo.FirstName = contactName;
  contactPersonalInfo.Surname = "recipient";

  contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));

  return contact;
}

After creating the contact, use the following sample code to add the contact to a recipient list.

  var repository = new ListManagerCollectionRepository();
  var recipientList = repository.GetEditableRecipientCollection(recipientListId);
  if (recipientList != null)
  {
    var xdbContact = new XdbContactId(contactId);
    if (!recipientList.Contains(xdbContact, true).Value)
    {
      recipientList.AddRecipient(xdbContact);
    }
  }
1
votes

Essentially you can follow this example

<%@ Page Language="c#" %>
<%@ Import Namespace="Sitecore.Analytics" %>
<%@ Import Namespace="Testing.ContactFacets.Model" %>
<!DOCTYPE html>
<html>
  <head>
    <title>Add Employee Data</title>
  </head>
  <body>
    <%
      var contact = Tracker.Current.Contact;
      var data = contact.GetFacet<IEmployeeData>("Employee Data");
      data.EmployeeId = "ABC123";
    %>
    <p>Employee data contact facet updated.</p>
    <p>Contact ID: <b><%=contact.ContactId.ToString()%></b></p>
    <p>Employee #: <b><%=data.EmployeeId%></b></p>
  </body>
</html>

The changes are then written when the session is abandoned, like so

<%@ Page language="c#" %>
<script runat="server">
  void Page_Load(object sender, System.EventArgs e) {
      Session.Abandon();
  }
</script> 
<!DOCTYPE html>
<html>
  <head>
    <title>Session Abandon</title>
  </head>
  <body>
  </body>
</html>

Follow this link for the source and more information - http://www.sitecore.net/learn/blogs/technical-blogs/getting-to-know-sitecore/posts/2014/09/introducing-contact-facets

0
votes

in case you have a tracker available and you dont need the update immediately, the following should work (note that the contact is added to the list upon session expiration):

//private const string ContactListTagName = "ContactLists";

var contact = Tracker.Current.Contact;

// Identify
if (contact.Identifiers.IdentificationLevel < ContactIdentificationLevel.Known)
{
    Tracker.Current.Session.Identify(email);
}

// Set Email
var contactEmail = contact.GetFacet<IContactEmailAddresses>("Emails");

// Create an email address if not already present

// This can be named anything, but must be the same as "Preferred" if you want
// this email to show in the Experience Profiles backend. 
if (!contactEmail.Entries.Contains("Preferred"))
    contactEmail.Entries.Create("Preferred");

// set the email
var emailEntry = contactEmail.Entries["Preferred"];
emailEntry.SmtpAddress = email;
contactEmail.Preferred = "Preferred";

// set FirstName and Surname (required for List Manager, "N/A" might not be ideal but I don't know how Sitecore behaves with empty strings)
var personal = contact.GetFacet<IContactPersonalInfo>("Personal");
personal.FirstName = personal.FirstName ?? "N/A";
personal.Surname = personal.Surname ?? "N/A";

// Add preferred language
var preferences = contact.GetFacet<IContactPreferences>("Preferences");
preferences.Language = Context.Language.Name;

// Here is the actual adding to the list by adding tags
using (new SecurityDisabler())
{
    var id = ID.Parse("CONTACTLISTID");
    contact.Tags.Set(ContactListTagName, id.ToString().ToUpperInvariant());
}

Greetz, Markus