Adding leads

Leads are a way to represent logged out users of your application, such as website visitors.

Whereas the users we have been referring to previously have logged into your app, leads are those who either haven't logged in or haven't signed up to your app yet. We therefore tend to have less data on these leads as we do with users. You can create, update, delete and view leads via the API.

If you need more information about the differences between users and leads you can refer to the Intercom Glossary for reference and clarification. As always, the Intercom API Reference is also a good place to check if you have further questions.

Leads and contacts

It should be noted that Leads were previously known as 'Contacts'. Our object names and types continue to be referred to as 'contacts/contact'. We will migrate to 'Leads/Lead' models at a future date.

Creating leads

Leads are similar to users except that we cannot set identifying characteristics such as user_id. This is assigned automatically. There are some other attributes which are available for users but not applicable to leads. You can find a description of these on the leads page in the API Reference Guide.

We can just create a simple wrapper for the create to allow you to choose which parameter you want to apply.

def create_lead(args)
    #Allow you to choose which parameters to apply
    @@intercom.contacts.create(args)
  end
require './intercom_client'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end
end

Then you can create leads as follows:

require './lead_tasks'
intercom = IntercomClient.new('<ACCESS TOKEN>');
lead = LeadTasks.new
lead.create_lead(email: "[email protected]")
lead.create_lead(email: "[email protected]", :name => "Socrates")

You should then be able to see your new leads in the your Intercom app:

1760

Find a lead

Let's create an easy way to search for your leads. You can list all your leads, or only those with a specific email address - let's search for all first, and then narrow the search with a specific email address. You can also search via user_id and id, but let's not make it so you have to choose which one to use and search for different options until we find one that matches or else returns an exception.

def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.contacts.all
      if not leads.empty?
        leads.each {|contact| puts "EMAIL: contact.email}, NAME: #{contact.name}", \
            "USER_ID: #{contact.user_id}, ID: #{contact.id}"}
      end
    else
      #Lets use the criteria in different ways to search contacts
        #Check against email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
                        "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end
require './intercom_client'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end

  def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.get("/contacts", "")
      if not leads.empty?
        leads['contacts'].each {|contact| puts "EMAIL: #{contact['email']}, NAME: #{contact['name']}", \
                                "USER_ID: #{contact['user_id']}, ID: #{contact['id']}"}
      end
    else
      #Lets use the criteria in differnent ways to serach contacts
        #Check againse email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
              "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end
end
> require './lead_tasks';
> intercom = IntercomClient.new('<ACCESS TOKEN>');
> lead = LeadTasks.new;
> lead.find_leads;
EMAIL: [email protected], NAME: Socrates
USER_ID: 1774da8e-92d5-4afd-9f56-161dc006cab2, ID: 5747f814d4e317f14f000cb3
EMAIL: [email protected], NAME:
USER_ID: 06e7fff5-d9f9-4d16-be87-9a5fbe8d519d, ID: 5747f7c1890d844b3c000e50
> single_lead = lead.find_leads('06e7fff5-d9f9-4d16-be87-9a5fbe8d519d');
single_lead.email
=> "[email protected]"
> single_lead = lead.find_leads('06e7fff5-d9f9-4d16-be87-9a5fbe8d519dXXX');
Intercom::ResourceNotFound: Contact Not Found
> single_lead = lead.find_leads('5747f7c1890d844b3c000e50');
> single_lead.email
=> "[email protected]"
> single_lead = lead.find_leads('1774da8e-92d5-4afd-9f56-161dc006cab2');
> single_lead.email=> "[email protected]"

Updating leads

Just like we can update the standard attributes of our contacts, we can also create and update the custom attributes of our leads.

Let's create a simple method which checks whether the attribute is a standard attribute and if not assumes it is a custom attribute that needs to be set or updated. We can do this by checking for the "AttributeNotSetError" exception and then assuming that this is a custom attribute value:

def update_lead_attrib(id_or_user_id, attrib=false, value=false)
    #First searchf or the lead and then check if it is custom or standard attribute
    lead = find_leads(id_or_user_id)
    begin
      #This will throw exception if not standard attribute
      lead.send(attrib)
      #If it is standard the simply set it to value
      lead.send("#{attrib}=", value)
    rescue Intercom::AttributeNotSetError
      #If not standard attribute then assume it is a custom attribute
      lead.custom_attributes[attrib] = value
    end
    #Either way we need to save the changed attribute at the end
    @@intercom.contacts.save(lead)
  end
require './intercom_client'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end

  def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.get("/contacts", "")
      if not leads.empty?
        leads['contacts'].each {|contact| puts "EMAIL: #{contact['email']}, NAME: #{contact['name']}", \
                                "USER_ID: #{contact['user_id']}, ID: #{contact['id']}"}
      end
    else
      #Lets use the criteria in differnent ways to serach contacts
        #Check againse email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
                        "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end

  def update_lead_attrib(id_or_user_id, attrib=false, value=false)
    #First searchf or the lead and then check if it is custom or standard attribute
    lead = find_leads(id_or_user_id)
    begin
      #This will throw exception if not standard attribute
      lead.send(attrib)
      #If it is standard the simply set it to value
      lead.send("#{attrib}=", value)
    rescue Intercom::AttributeNotSetError
      #If not standard attribute then assume it is a custom attribute
      lead.custom_attributes[attrib] = value
    end
    #Either way we need to save the changed attribute at the end
    @@intercom.contacts.save(lead)
  end

end

We can then set some attributes as follows:

> single_lead = lead.find_leads("[email protected]");
EMAIL: [email protected], NAME:
USER_ID: 06e7fff5-d9f9-4d16-be87-9a5fbe8d519d, ID: 5747f7c1890d844b3c000e50
> single_lead = lead.find_leads("5747f7c1890d844b3c000e50");
> single_lead.name
=> nil
> single_lead.email
=> "[email protected]"
> single_lead.update
single_lead.update_verb  single_lead.updated_at   single_lead.updated_at=
> single_lead.update
single_lead.update_verb  single_lead.updated_at   single_lead.updated_at=
> lead.update_lead_attrib("5747f7c1890d844b3c000e50", "name", "Plato")
> single_lead = lead.find_leads("5747f7c1890d844b3c000e50");
> single_lead.name
=> "Plato"
> lead.update_lead_attrib("5747f7c1890d844b3c000e50", "Published", "The Republic")
> single_lead = lead.find_leads("5747f7c1890d844b3c000e50");
> single_lead.custom_attributes
=> {"Published"=>"The Republic"}

Converting leads to users

You can manually convert leads to users using the Ruby SDK. However, you need to have a pre-existing user.

The API endpoint for converting leads allows you to provide a JSON file with contact and user data. The endpoint then simply creates a user and performs a merge of a lead with that new user.

So let's write a simple method to use the Ruby convert method which assumes that a user already exists and we simply want to merge the lead with this user. Let's allow this method to be used by simply passing in a lead user_id or id and a user object identifier. This way we can search for the lead and user to ensure they exist before perform the merge:

def merge_leads(contact_id_or_id, user_criteria)
    lead = find_leads(contact_id_or_id)
    #Check if the user exists
    usr = UserTasks.new
    user = usr.find_user(user_criteria)

    @@intercom.contacts.convert(lead, user)
  end
require './intercom_client'
require './user_tasks'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end

  def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.get("/contacts", "")
      if not leads.empty?
        leads['contacts'].each {|contact| puts "EMAIL: #{contact['email']}, NAME: #{contact['name']}", \
                                "USER_ID: #{contact['user_id']}, ID: #{contact['id']}"}
      end
    else
      #Lets use the criteria in differnent ways to serach contacts
        #Check againse email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
                        "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end

  def update_lead_attrib(id_or_user_id, attrib=false, value=false)
    #First searchf or the lead and then check if it is custom or standard attribute
    lead = find_leads(id_or_user_id)
    begin
      #This will throw exception if not standard attribute
      lead.send(attrib)
      #If it is standard the simply set it to value
      lead.send("#{attrib}=", value)
    rescue Intercom::AttributeNotSetError
      #If not standard attribute then assume it is a custom attribute
      lead.custom_attributes[attrib] = value
    end
    #Either way we need to save the changed attribute at the end
    @@intercom.contacts.save(lead)
  end

  def merge_leads(contact_id_or_id, user_criteria)
    lead = find_leads(contact_id_or_id)
    #Check if the user exists
    usr = UserTasks.new
    user = usr.find_user(user_criteria)

    @@intercom.contacts.convert(lead, user)
  end
end

Then we can merge leads with a user as follows:

> usr.create_user(email: "[email protected]", name: "Al", user_id: "1942") #Use a current user if it already exists. Just remeber the fields so you can check what has changed
> new_lead = lead.create_lead(email: "[email protected]", :name => "Meursault", :last_request_at => Time.now.to_i);
> new_lead.last_request_at
=> 2016-05-31 10:01:11 +0000
> new_lead.id
=> "574d60e8666dd69e11000148"
> lead.merge_leads("574d60e8666dd69e11000148", "1942")
=> #<Intercom::User:0x000000014ad318
> merged_user = usr.find_user("1942");
> merged_user.last_request_at
=> 2016-05-31 10:01:11 +0000
> merged_user.name
=> "Al"
> merged_user.email
=> "[email protected]"
> merged_user.user_id
=> "1942"
> merged_user.id
=> "574d58df7c83dd7750000039"

You can see that when a merge occurs the user retains their id, user_id and email values. Other values will be taken from the lead such as the last_request_at which we set for this lead. You can see more details of this on the API reference page.

What if we do not have a user we want to merge the lead to? Then we can create another method to convert a lead to a user when no user exists:

def convert_leads(contact_id_or_id, new_user_id, options={})
    #If no lead is found an exception will be returned
    lead = find_leads(contact_id_or_id)
    #Set some defaults if not set by user
    defaults ={
        :user_id => new_user_id,
        :email => nil,
        :name => nil,
    }
    options = defaults.merge(options)
    puts options
    #Create new Json object to pass through to endpoint
    new_user = {
        contact: {
            :user_id => lead.user_id,
        },
        user: {}
    }
    new_user = new_user.merge(:user => options)
    puts new_user

    @@intercom.post("/contacts/convert", new_user)
  end
require './intercom_client'
require './user_tasks'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end

  def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.get("/contacts", "")
      if not leads.empty?
        leads['contacts'].each {|contact| puts "EMAIL: #{contact['email']}, NAME: #{contact['name']}", \
                                "USER_ID: #{contact['user_id']}, ID: #{contact['id']}"}
      end
    else
      #Lets use the criteria in differnent ways to serach contacts
        #Check againse email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
                        "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end

  def update_lead_attrib(id_or_user_id, attrib=false, value=false)
    #First searchf or the lead and then check if it is custom or standard attribute
    lead = find_leads(id_or_user_id)
    begin
      #This will throw exception if not standard attribute
      lead.send(attrib)
      #If it is standard the simply set it to value
      lead.send("#{attrib}=", value)
    rescue Intercom::AttributeNotSetError
      #If not standard attribute then assume it is a custom attribute
      lead.custom_attributes[attrib] = value
    end
    #Either way we need to save the changed attribute at the end
    @@intercom.contacts.save(lead)
  end

  def convert_leads(contact_id_or_id, new_user_id, options={})
    #If no lead is found an exception will be returned
    lead = find_leads(contact_id_or_id)
    #Set some defaults if not set by user
    defaults ={
        :user_id => new_user_id,
        :email => nil,
        :name => nil,
    }
    options = defaults.merge(options)
    #Create new Json object to pass through to endpoint
    new_user = {
        contact: {
            :user_id => lead.user_id,
        },
        user: {}
    }
    new_user = new_user.merge(:user => options)

    @@intercom.post("/contacts/convert", new_user)
  end

  def merge_leads(contact_id_or_id, user_criteria)
    lead = find_leads(contact_id_or_id)
    #Check if the user exists
    usr = UserTasks.new
    user = usr.find_user(user_criteria)

    @@intercom.contacts.convert(lead, user)
  end
end

Now we can convert a lead by simply passing in a new user_id which we will use to create a new user:

> lead.create_lead(email: "[email protected]", :name => "Meursault", :last_request_at => Time.now.to_i);
> lead.find_leads;
EMAIL: [email protected], NAME: Meursault
USER_ID: 80dc3d19-675b-43b3-9d72-450e7ee34e16, ID: 574d64c7e1dd8e194600008f
> lead.convert_leads("574d64c7e1dd8e194600008f", "[email protected]");
> lead.find_leads;

> new_user = usr.find_user("[email protected]");
> new_user.email
=> "[email protected]"
> new_user.name
=> "Meursault"
> new_user.id
=> "574d64c7e1dd8e194600008f"

You can add other identifiers to the parameters, since the options parameter allows you to add multiple optional parameters if you want these to be set for your new user. It is basically a shortcut for creating your own user as a separate action.

Deleting leads

And finally you can delete any lead which you don't want to merge or convert. You might need to do this when you have duplicate leads which you do not need. Let's create a method to let you delete leads by providing a lead id or lead user id:

def delete_lead(contact_id_or_id)
    lead = find_leads(contact_id_or_id)
    @@intercom.contacts.delete(lead)
  end
require './intercom_client'
require './user_tasks'

class LeadTasks < IntercomClient
  def initialize
  end

  def create_lead(args)
    #Allow people to choose which parameters to apply
    @@intercom.contacts.create(args)
  end

  def find_leads(criteria=false)
    #No criteria means search all by default
    if not criteria
      leads = @@intercom.get("/contacts", "")
      if not leads.empty?
        leads['contacts'].each {|contact| puts "EMAIL: #{contact['email']}, NAME: #{contact['name']}", \
                                "USER_ID: #{contact['user_id']}, ID: #{contact['id']}"}
      end
    else
      #Lets use the criteria in differnent ways to serach contacts
        #Check againse email
        lead_list = @@intercom.contacts.find_all(:email => criteria)
        #Check if email returned anything
        if lead_list.any?
          lead_list.each {|lead| puts "EMAIL: #{lead.email}, NAME: #{lead.name}", \
                        "USER_ID: #{lead.user_id}, ID: #{lead.id}"}
        else
          begin
            lead = @@intercom.contacts.find(user_id: criteria)
            return lead
          rescue Intercom::ResourceNotFound
            lead = @@intercom.contacts.find(id: criteria)
            return lead
          end
        end
    end
  end

  def update_lead_attrib(id_or_user_id, attrib=false, value=false)
    #First searchf or the lead and then check if it is custom or standard attribute
    lead = find_leads(id_or_user_id)
    begin
      #This will throw exception if not standard attribute
      lead.send(attrib)
      #If it is standard the simply set it to value
      lead.send("#{attrib}=", value)
    rescue Intercom::AttributeNotSetError
      #If not standard attribute then assume it is a custom attribute
      lead.custom_attributes[attrib] = value
    end
    #Either way we need to save the changed attribute at the end
    @@intercom.contacts.save(lead)
  end

  def convert_leads(lead_id_or_id, lead_email, options={})
    #If no lead is found an exception will be returned
    lead = find_leads(lead_id_or_id)
    #Set some defaults if not set by user
    defaults ={
        :user_id => nil,
        :email => lead_email,
        :name => nil,
    }
    options = defaults.merge(options)
    #Create new Json object to pass through to endpoint
    new_user = {
        contact: {
            :user_id => lead.user_id,
        },
        user: {}
    }
    new_user = new_user.merge(:user => options)

    @@intercom.post("/contacts/convert", new_user)
  end

  def merge_leads(lead_id_or_id, user_criteria)
    lead = find_leads(lead_id_or_id)
    #Check if the user exists
    usr = UserTasks.new
    user = usr.find_user(user_criteria)

    @@intercom.contacts.convert(lead, user)
  end

  def delete_lead(contact_id_or_id)
    lead = find_leads(contact_id_or_id)
    @@intercom.contacts.delete(lead)
  end
end

So let's create a duplicate lead we don't need and delete it:

> lead.create_lead(email: "[email protected]", :name => "Meursault", :last_request_at => Time.now.to_i);
> lead.find_leads;
EMAIL: [email protected], NAME: Meursault10
USER_ID: 627d6227-86ca-4844-9eb7-69f846a7cb8e, ID: 574d6708b87ffae5a4000001
> lead.delete_lead("574d6960125ea63a25000045");
lead.find_leads;