Our Intercom API Integration using Ruby as an Example

I asked Joe, our CTO, to cover how the Intercom API integration with our app is done using Ruby. He gave me an overview of the Rails job that syncs data between our app and Intercom and gave me the code below, to which I've added some comments.

Related:  Learn more about Intercom including Intercom hacks in these articles.

Upscope is a co-browsing (one click to see the customer's screen) service and we use Intercom for live chat support.

While supporting customers we need to have Intercom synced with our app so we so we can quickly help customers.

For example, we need to sync up custom attributes so we can add a link in Intercom directly to the admin page for that customer, see their monthly app usage figures, see when they subscribed and more.

While the Intercom widget integration is a simple copy and paste, it's the database sync between Intercom and our database that requires some work.

Ideally we want Intercom to be up to date with the latest data from our database that has changed during their interactions with Upscope.

Below you'll see the Rails job that:

  1. Creates a new user or updates an existing user in Intercom.
  2. Updates which teams they belong to as one user can be part of several teams.
  3. Updates their timezone as sometimes Intercom has a better information on that.
  4. Updates their name when Intercom has it but we don't as it's manually inputted.
  5. Updates their phone number, which again might be manually inputted.
  6. Updates Intercom attributes using data from our database.
  7. Merges a lead into a user.
class SyncWithIntercomJob < ApplicationJob
  queue_as :crm_sync
  # Creates a user in intercom if it does not exist. If it does exist, it updates it
  def perform(user)
    return if ENV['INTERCOM_ACCESS_TOKEN'].nil?
    return unless ENV['INTERCOM_SYNC_ENABLED'].true?

    # Gets time zone to reset so we know which it is in case we change it
    old_time_zone = Time.zone


    # Creates the intercom client with that access token
    intercom = Intercom::Client.new(token: ENV['INTERCOM_ACCESS_TOKEN'], handle_rate_limit: true)
    intercom_user = begin
    				  # tries to find user with this id
                      intercom.users.find(user_id: user.id) 
                    # throws exception  
                    rescue Intercom::ResourceNotFound
                      # creates one with that user id
                      intercom.users.create(email: user.email, user_id: user.id)
                    end
	# We store intercom id in our db
    user.update metadata: { intercom_user_id: intercom_user.id }

    # Sometimes intercom knows time zone of user and we don't so we use their information on the time zone
    user_time_zone = intercom_user.try(:location_data).try(:timezone)
    if user_time_zone.present?
      begin
        # Updates timezone to user
        Time.zone = user_time_zone

        # Saves timezone
        user.update! timezone: user_time_zone
      rescue ArgumentError
        logger.error "Ignored invalid timezone #{user_time_zone}"
      end
    end

    # Adds the teams the user belongs to, remove ones in intercom they no longer belong to as a user can be part of multiple teams on Upscope
    intercom_user_companies_ids = intercom_user.companies.map(&:company_id)
    user_teams_ids = user.teams.map(&:id)
    intercom_user.companies = (intercom_user_companies_ids + user_teams_ids).uniq.map do |id|
      {
        company_id: id,
        remove: !id.in?(user_teams_ids) || nil
      }
    end


    # Sometimes they sign up but we don't have their name but sometimes we add it manually
    if user.name?
      # If we have the name of the person in Upscope, set to intercom
      intercom_user.name = user.name
    elsif intercom_user.name.present? && intercom_user.name.length > 1 && !user.from_oauth?
      # If we have the name in intercom but not Upscope, update Upscope
      user.update name: intercom_user.name
    else
      # Set intercom name to nil
      intercom_user.name = nil
    end

    # Grab phone number from intercom. If phone number is manually added to intercom, we grab it
    if user.phone_number.nil? && intercom_user.phone.present? && !user.from_oauth?
      user.update phone_number: intercom_user.phone
      user.reload
    end

    # Here we are updating Intercom from our records
    intercom_user.email = user.email
    intercom_user.phone = user.phone_number
    intercom_user.created_at = user.created_at

    # Make sure that, in both intercom and our app, the last request is up to date
    user.last_request_at = [user.last_request_at, intercom_user.last_request_at].compact.max
    intercom_user.last_request_at = user.last_request_at

    # Add the custom attributes for that user to intercom, from our database
    intercom_user.custom_attributes = user.as_json(with_everything: true,
                                                   except: [:name, :email, :phone_number, :id, :created_at, :last_request_at, :_type])
                                          .merge(deleted: false)

    intercom.users.save(intercom_user)

    # Merge lead if exists. Sometimes there's a lead in intercom which is not a user.If the user was created in the last 24 hours, it looks for a contact with the same email address and merges it.
    if user.created_at > 24.hours.ago
      # Find lead
      begin
        intercom_lead = intercom.contacts.find_all(email: user.email).first
        intercom.contacts.convert(intercom_lead, intercom_user) if intercom_lead
        logger.info 'Merged contact into user'
      rescue Intercom::ResourceNotFound
        nil
      end
    end

    user.owned_teams.each do |team|
      intercom_company = begin
                           intercom.companies.find(company_id: team.id)
                         rescue Intercom::ResourceNotFound
                           intercom.companies.create(company_id: team.id)
                         end
      intercom_company.name = team.domain
      intercom_company.created_at = team.created_at
      intercom_company.monthly_spend = team.monthly_spend
      intercom_company.custom_attributes = team.as_json(
        with_everything: true, except: [:created_at, :id, :_type]
      ).merge(deleted: false)

      intercom.companies.save(intercom_company)

      team.update metadata: { intercom_company_id: intercom_company.id }
    end
  ensure
    Time.zone = old_time_zone
  end
end

Which attributes do we sync up that you might find useful?

Admin link from Intercom to your own website's admin section.

We use this every day, many times a day. When an existing customer asks a question, we need to see their account to understand their context in full. We do this by clicking the admin linking in the Intercom custom attributes list.

Upscope's own instant screen sharing link

If they need help, we can see what they see in one click. Add this using our own Upscope, which is an official app on the intercom app store.

Annual savings attribute so you can remind them to switch

This custom attribute might for example say: Annual saving $316

If they’ve been on a monthly plan for a while, use this during a chat to remind them of savings they'll make by switching to an annual plan.

Other attributes?

You can see the above and other ideas for Intercom attributes listed here.

Add our JS snippet and see the customer's screen from Intercom

Upscope not only uses Intercom but also integrates with it.

While chatting, you can click on link to instantly, without downloads, see what the customer sees and click for them.

Do this by adding the Upscope javascript snippet on the same page as the Intercom snippet and you have ready to go instant screen sharing.

Start a trial here and you can also use our Intercom to chat to our CTO Joe if you have more questions about using Intercom's API.

If you want to learn more about Intercom, including a set of Intercom hacks then see our experience in these articles.

Show users your website like never before

Click to play with audio
Learn more about Upscope
Pardeep Kullar

Pardeep Kullar

Pardeep overlooks growth at Upscope cobrowsing and loves writing about SaaS companies, customer success and customer experience.

Read More

Subscribe to Upscope Blog!