Template used: Crust 🍞
This is a simple API for integrating Intercom with Archer Affiliates. It is built using TypeScript, Axios, and Zod, and provides a simple set of types and methods required to interact with the Intercom API.
- Messenger Script
- Ticketing
Whenever you intend to integrate another app with intercom using this API, follow these steps:
npm install @archer2024/intercom-api
INTERCOM_APP_ID=your_app_id
INTERCOM_ACCESS_TOKEN=your_access_token
You can find the INTERCOM_APP_ID
in your Intercom settings, and the INTERCOM_ACCESS_TOKEN
in your Intercom developer workspace settings.
Go to your root HTML file, _document.jsx in case of Next.js, import the generateIntercomScript
function from @archer2024/intercom-api/client
:
import { generateIntercomScript } from "@archer2024/intercom-api/client";
This function generates a stringified script that you can add to your HTML file using a script tag, like so:
<script>
{
generateIntercomScript({ appId: process.env.INTERCOM_APP_ID });
}
</script>
Or in React, using the dangerouslySetInnerHTML
prop:
<script
dangerouslySetInnerHTML={{
__html: generateIntercomScript({ appId: process.env.INTERCOM_APP_ID }),
}}
/>
Now, start your dev server and, if everything is set up correctly, you should see the little FAB on the bottom right corner of your screen, click it and voila! You can chat with your users.
For this, we use Intercom's ticketing system, each contact form submission creates a ticket which is then handled using the Intercom dashboard. This is a multi-step process, follow carefully:
-
First, understand that Intercom doesn't allow clients/browsers to directly interact with its API, so we need a server to act as a middleman. This is where the
@archer2024/intercom-api/server
package comes in. -
Setup the server endpoint, you can use whatever server framework you're working with, as long as you get the endpoint right. For now, I've only added the ability to have one fixed endpoint to create tickets, which is
/api/intercom/tickets
. You can contribute to this package and make the endpoint a parameter if you want, I'd be happy to merge your PR. -
Have a POST request handler at the mentioned endpoint, and pass the request body to the
createTicket
function from@archer2024/intercom-api/server
. This is an asynchronous function so you can either use promises or async/await and handle errors. It will simply create a ticket in Intercom and return the response:
import { createTicket } from "@archer2024/intercom-api/server";
- The request body is always of the type
NewTicket
, which is basically an exact copy of the Intercom API's ticket object. You can find the type in the@archer2024/intercom-api/tickets
package. For the sake of simplicity, here's the actual type:
type NewUserTicket = {
contacts: [
{
email: string;
}
];
ticket_type_id: "1" | "2" | "3" | "4" | "5" | "6" | "7";
ticket_attributes: {
_default_title_: string;
_default_description_?: string | undefined;
user_id?: string;
username?: string;
};
};
This is the request object, here's a breakdown:
-
contacts
is an array of objects, except you must always send one array with one object with one email. This is the email of the user who submitted the form. -
ticket_type_id
is the type of ticket you want to create, you can manage ticket types from the Intercom dashboard, Archer, as of writing this, has tickets of 5 types:
export const ticketTypeWebsiteId = "1";
export const ticketTypeBugId = "2";
export const ticketTypeFeatureId = "3";
export const ticketTypeInternalId = "4";
export const ticketTypeAffiliateId = "5";
export const ticketTypeBrandId = "6";
export const ticketTypePortalId = "7";
Whenever you send a request, import one of these from the @archer2024/intercom-api/tickets
package and use it as the ticket_type_id
, don't ever use raw strings, that's just bad practice.
-
ticket_attributes
is an object with two keys,_default_title_
and_default_description_
. The title is always required, the description is optional. You should also senduser_id
and ausername
in case of authenticated users, but these are optional. -
This is what the final server handler would look like if you were using Next.js with the pages directory:
- Create the Axios Instance made specifically for Intercom API, this is done using the
generateIntercomApi
function from@archer2024/intercom-api/shared
. This function takes an object with theaccessToken
property, which is your Intercom access token, and returns an Axios instance with the necessary headers to interact with the Intercom API. You can use this instance to make requests to the Intercom API anywhere from the server.
/pages/aip / intercom / tickets.ts;
import { createTicket } from "@archer2024/intercom-api/server";
import {
generateIntercomApi,
IntercomApiResponse,
} from "@archer2024/intercom-api/shared";
import { ZodError } from "zod";
import type { NextApiRequest, NextApiResponse } from "next";
const api = generateIntercomApi({
accessToken: process.env.INTERCOM_ACCESS_TOKEN,
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<IntercomApiResponse>
) {
if (req.method === "POST") {
try {
// Create the ticket on Intercom
const { data } = await createTicket({ api, newTicket: req.body });
// Process a POST request
res.status(200).json({ message: "Ticket created", data });
} catch (e: unknown) {
if (e instanceof ZodError) {
res.status(400).json({ message: "Bad Request", issues: e.errors });
} else {
res.status(500).json({ message: "Internal server error" });
}
}
}
}
Note that we forward the whole request body as it is to the createTicket
function, this is since the functions uses a Zod schema underneath to match the NewTicket
type, and will throw an error if the request body doesn't match the type, so you don't need to worry about anything.
On the client side, you have a similar function named createTicket
which takes the exact same NewTicket
type as the only argument and sends a POST request to the server endpoint. This function is also asynchronous, so you can use promises or async/await and handle errors. It will return the response from the server:
import { createTicket } from "@archer2024/intercom-api/client";
Here's how you can use it in a React component:
import { createTicket } from "@archer2024/intercom-api/client";
import { ticketTypeWebsiteId } from "@archer2024/intercom-api/tickets";
export default function ContactForm() {
const handleSubmit = async (e) => {
e.preventDefault();
const form = e.target;
const newTicket = {
contacts: [{ email: form.email.value }],
ticket_type_id: ticketTypeWebsiteId,
ticket_attributes: {
_default_title_: form.subject.value,
_default_description_: form.message.value,
},
};
try {
const response = await createTicket(newTicket);
console.log(response);
} catch (e) {
console.error(e);
}
};
}
This function parses the newTicket using the same NewTicket
Zod schema, and sends a POST request to the server endpoint with the parsed object as the request body. The server then creates a ticket on Intercom and returns the response. This ensures double validation, once on the client side and once on the server side.
And that's it! You've successfully integrated Intercom with your app. If you have any questions, feel free to ask, my email is kashanahmad.me@gmail.com and I'm always happy to help.
We are always looking for ways to improve and make ourselves better. If you have any suggestions, ideas, or feedback, please open an issue or a pull request.
This is open source software released under the MIT License. We encourage you to use, modify, and distribute it as you see fit.