Download leads from the Facebook API

Scenario

Contoso Water Purifiers use a Facebook page to advertise their products to generate leads. When a potential customer views their page and shows interest in a particular product, they enter their contact details into leads form (which is available on the Facebook page). To facilitate easy retrieval of these leads, the business tasks their IT department with writing an app to downloads customer leads from Facebook using the Facebook REST API. Although not discussed in this post, the leads are then entered into the business’s internal IT systems.

Implementation

This section demonstrates how a developer from the IT department implements this requirement. The steps outline how to write a C# console app (.NET Framework) to connect to the Facebook REST API and download leads.

1.) Retrieve the leads form Id from within the business’ Facebook page (Figure 1)

Figure 1

2.) Register to use developers.facebook.com/apps/ and create a Facebook app by selecting ‘Manage Business Integrations’.

3.) Use the Facebook Graph API explorer to generate an access token and use this token to validate that the Facebook REST API is working as expected (Figure 2).

Figure 2

4.) Take the Facebook REST API JSON response and paste it into Visual Studio by selecting ‘Paste Special’, ‘Paste JSON As Classes’. This generates the schema ‘model’ shown in the following code snippet. The Facebook JSON response deserialisation is based on this schema

using System;
using System.Runtime.Serialization;

namespace Contoso_Leads_Configuration
{
    [DataContract]
    public class FacebookLeads
    {
        [DataMember]
        public Datum[] data { get; set; }
        [DataMember]
        public Paging paging { get; set; }
        [DataContract]
        public class Paging
        {
            [DataMember]
            public Cursors cursors { get; set; }
        }
        [DataContract]
        public class Cursors
        {
            [DataMember]
            public string before { get; set; }
        }
        [DataContract]
        public class Datum
        {
            [DataMember]
            public DateTime created_time { get; set; }
            [DataMember]
            public string id { get; set; }
            [DataMember]
            public Field_Data[] field_data { get; set; }
        }
        [DataContract]
        public class Field_Data
        {
            [DataMember]
            public string name { get; set; }
            [DataMember]
            public string[] values { get; set; }
        }
    }
}

5.) Write the C# code displayed in the code snippet below

  • The HttpClient GetAsync() call (line 31) executes and makes an asynchronous call to the Facebook REST API. This is a non blocking call and will suspend the function RetrieveLeadsfromFacebookForm() and return immediately to the caller (line 17).
  • The async call (line 31) returns, and progresses to line 37. This line deserialises the Facebook REST API JSON response into an object called FacebookLeads (refer to the code snippet above)
  • The FacebookLeads object (Figure 3) on line 17 is populated
class Program
{
    private static readonly HttpClient client = new System.Net.Http.HttpClient();

    static void Main(string[] args)
    {
         IOrganizationService crmService = GetCrmService();
         EntityCollection SocialLeadsConfiguration = GetSocialLeadsConfiguration(crmService);
         client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ConfigurationManager.AppSettings["facebookAuthorization"]); //"EAAuJsAvHM(QB...
         client.BaseAddress = new Uri(ConfigurationManager.AppSettings["facebookUri"]); //new Uri("https://graph.facebook.com/v8.0/");

         var facebookFormId = (String)socialLeadsConfiguration.Attributes["cpl_formid"]; //"365918717791871";
         DateTime facebookLastSyncedDate = (DateTime)socialLeadsConfiguration.Attributes["cpl_lastsynceddate"]; //DateTime.UtcNow.AddDays(-7);
         Int32 facebookLastSyncedDateUnixTimestamp = (Int32)(facebookLastSyncedDate.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
         DateTime facebookCurrSyncedDateUnixTimestamp = DateTime.UtcNow;
                       
         FacebookLeads facebookLeads = RetrieveLeadsFromFacebookForm(facebookFormId, crmService, socialLeadsConfiguration, facebookLastSyncedDateUnixTimestamp, facebookCurrSyncedDateUnixTimestamp).Result;
         if (facebookLeads != null)
         {           
              SaveLeadsFromFacebookForm(crmService, facebookLeads, socialLeadsConfiguration, projectRef);
              UpdateSocialLeadsLastSyncedDate(crmService, socialLeadsConfiguration, facebookCurrSyncedDateUnixTimestamp);
         }
    }

    public static async Task<FacebookLeads> RetrieveLeadsFromFacebookForm(String facebookFormId, IOrganizationService crmService, Entity socialLeadsConfiguration, Int32 facebookLastSyncedDateUnixTimestamp, DateTime facebookCurrSyncedDateUnixTimestamp)
        {
            try
            {
                HttpResponseMessage response = new HttpResponseMessage();

                response = await client.GetAsync(facebookFormId + "/leads?filtering=[{\"field\":\"time_created\",\"operator\":\"GREATER_THAN\",\"value\":" + facebookLastSyncedDateUnixTimestamp + "}]");

                if (response.IsSuccessStatusCode)
                {
                    string jsonString = string.Empty;
                    jsonString = await response.Content.ReadAsStringAsync();
                    FacebookLeads facebookLeads = JsonConvert.DeserializeObject<FacebookLeads>(jsonString);
                    return facebookLeads;
                }
                return null;
            }
            catch (Exception e)
            {
                Console.WriteLine("The following exception has been generated " + e);
                return null;
            }
        }
   }
Figure 3

Referring to line 8 in the code snippet below, the first ‘x’ represents a list of name/value pairs. The value returned is the value associated to ‘email’.

public static void SaveLeadsFromFacebookForm(IOrganizationService crmService, FacebookLeads facebookLeads, Entity socialLeadsConfiguration, EntityReference projectRef)
{
    foreach (var item in facebookLeads.data)
    {
        try
        {
            List<Field_Data> facebookLead = item.field_data.ToList();
            string email = facebookLead.SingleOrDefault(x => x.name.Equals("email"))?.values[0];
            string firstname = facebookLead.SingleOrDefault(x => x.name.Equals("first_name"))?.values[0];
            string lastname = facebookLead.SingleOrDefault(x => x.name.Equals("last_name"))?.values[0];
            string phonenumber = facebookLead.SingleOrDefault(x => x.name.Equals("phone_number"))?.values[0];            

6.) View the values extracted from the JSON response in Figure 4

Figure 4

Further Reading

Download leads from the Facebook API issue

References

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators

c#6 – Null-Conditional Operator

https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-8.0