Notes from deploying a chat management app:

User Interacts via: FB Page (FB Messenger), LINE, App

User Cannot Interact via: Instagram (no API access to messages)

Two Architecture Options

Architecture: FB Messenger Bot, LINE Bot, AWS API Gateway, AWS Lambda, AWS DynamoDB, Twilio Conversations API, Twilio Programmable Chat API

I got well down the road with this implementation, and will share function code later but decided to stick with adding to an existing Rails API deployed on Elastic Beanstalk to speed up development. I think long term the API Gateway/Lambda approach is the way to go for affordable scaling. Starting small with an existing app allowed me to move quickly and finish the initial prototype in a couple of days.

Alternative Architecture (ended up moving forward with this for now): FB Messenger Bot, LINE Bot, Rails API deployed on AWS Elastic Beanstalk, AWS RDS for persisting User info, Twilio Conversations API, Twilio Programmable Chat API

Steps from 0 to Deployment

  1. Create a Programmable Chat Service
  2. Create Programmable Chat User
  3. Create Programmable Chat Channel
  4. Create Programmable Chat Member from existing Chat User (user has many member identities)
  5. Add Member to Channel
  6. Handling Conversations Part 1: BOTS
    • LINE Bot
      • Create LINE Bot
      • Configure webhooks
    • WhatsApp Bot (Skipped)
    • FB Messenger Bot
      • Create FB MESSENGER Bot
      • Configure webhooks
    • A Note on Instagram from a frustrated developer (you’re screwed)
    • FB Creator Studio might give programmatic access but I doubt it.
  7. Handling Conversations part 2: SMS and Connections
    • Configure SMS to receive messages
    • Connecting to Ongoing Conversation
  8. ADMIN Management of Many Conversations, Hopping in and out of Channels, Closing Conversations, Inviting Users to Delegate Conversations
  9. Cleanup: Archiving Conversations to s3

1. Creating a Chat Service

    1 require 'twilio-ruby'                                                           
    2   
    3 class TwilioApi                                                                 
    4                                                                                 
    5   def initialize                                                                
    6     account_sid = ENV['twilio_account_id']                                      
    7     auth_token = ENV['twilio_auth_token']                                       
    8     @client = Twilio::REST::Client.new(account_sid, auth_token)                 
    9   end 
   10
   11   def create_chat_service(name)                                                 
   12     service = @client.chat.services.create(                                     
   13       friendly_name: name                                                       
   14     )                                                                           
   15     return service                                                              
   16   end 

I created a Twilio API wrapper using the ruby-twilio gem, initialized it using environment variables from my Twilio Account, and just followed the instructions to create a chat service.

The returned object has the unique id I need, the service’s SID, which I save on the Account object. An Account will have many Users (members of the org managing conversations) and Clients (potentially anonymous clients who might or might not authenticate or place orders)

The Account now has a canonical Twilio Chat Service for their Account, all Users and Clients of this Account will now be created against this Chat Service.

2. Creating a Chat User

   28   def create_chat_user(chat_service_id, client_guid, client_username)           
   29     #attributes = {}                                                            
   30     #                                                                           
   31     #username should be email but unauthenticated users                         
   32     #could have anonymous identifiers like Big Red Dog and then                 
   33     #become associated with an email or phone number later                      
   34     #                                                                           
   35     #user.friendly_name = ""                                                    
   36     user = @client.chat.services(chat_service_id)                               
   37     .users                                                                      
   38     .create(identity: client_guid, friendly_name: client_username)              
   39     return user                                                                 
   40   end  

When a Client comes to the site and starts interacting with Chat, we will create and persist a Client object. A guid is automatically generated on an after_create hook and that is used for the identity. It’s important to use this guid to create the identity and not the generated anonymous username, because the guid will not change even if we learn more about the user like phone or email, while the username will change if the Client opts to de-anonymize themselves.

Your other option is to require an email or phone number prior to starting chat but this might drive down engagement. And the only way to ensure you’re not getting a fake email just to start the chat (exmaple@example.com) is to send a challenge token, this is way too many steps for customer support or cold leads to go through just to chat.

Main Takeaway: The identity cannot change so use something that will not change to create it.

3. Creating a Chat Channel

4-5. Creating a Chat Member from an Existing Chat User and adding to Channel

6-7. Handling Conversations, Creating Bots, Configuring Webhooks, Configuring Programmable SMS and handling TwiML

8. The Admin User, Managing Many Conversations and Channels

9. Cleanup and Archiving