Respond to customer reviews

Overview

This recipe demonstrates how to use Airtop SDK to automate responses to customer reviews in a restaurant’s Facebook page.

The script below will start an Airtop session, go to Facebook, ask the user to sign-in if required and respond to the first uncommented customer review.

Try the live example of this recipe

Even though this recipe will walk you through the CLI script, the project contains a Vercel application that you can run locally in your browser.

Prerequisites

To get started, ensure you have:

  • Node.js version 20+ installed on your system.
  • An Airtop API key. You can get one for free.

Getting Started

  1. Clone the repository

    Start by cloning the source code from GitHub:

    $git clone https://github.com/airtop-ai/examples-typescript.git
    >cd examples-typescript
  2. Install dependencies

    Run the following command to install the necessary dependencies, including the Airtop SDK:

    $pnpm install

    We use turbo to build all the necessary packages in the examples repo. Build the packages by running:

    $turbo build:packages

    Follow the turbo installation guide to set it up.

  3. Run the script

    Go to the project folder and run the Node.js script:

    $cd examples/customer-reviews
    >pnpm run cli

Script Walkthrough

The script in src/cli.ts performs the following steps:

  1. Initialize the Airtop session

    First, we ask for an Airtop API key and an optional Profile ID in order to initialize the FacebookCommenterService class which is responsible for the session management.

    cli.ts
    1const service = new FacebookCommenterService({ apiKey, log })
    2//...
    3sessionAndWindow = await service.initializeSessionAndBrowser(profileId);

    Under the Hood

    facebook-commenter.service.ts - initializeSessionAndBrowser
    1const session = await this.client.sessions.create({
    2 configuration: { /* config params */ },
    3});
    4
    5if (!session.data.cdpWsUrl) {
    6 throw new Error("Unable to get cdp url");
    7}
    8
    9const windowResponse = await this.client.windows.create(session.data.id, { url: LOGIN_URL });
    10const windowInfo = await this.client.windows.getWindowInfo(session.data.id, windowResponse.data.windowId);
    11
    12return { session, windowInfo }
  2. Verify if the user is signed-in

    We prompt the home page to verify if the user has signed-in before we continue. In case you need to enter your Facebook credentials you will see printed in the console a link to the session’s Live View in which you can safely log in to your account.

    cli.ts
    1const isSignedIn = await service.checkIfSignedIntoWebsite({ sessionId, windowId });

    Under the Hood

    facebook-commenter.service.ts - checkIfSignedIntoWebsite
    1const isLoggedInPromptResponse = await this.client.windows.pageQuery(sessionId, windowId, {
    2 prompt: IS_LOGGED_IN_PROMPT,
    3 configuration: {
    4 outputSchema: IS_LOGGED_IN_OUTPUT_SCHEMA,
    5 },
    6});
    7
    8const parsedResponse = JSON.parse(isLoggedInPromptResponse.data.modelResponse);
    9
    10if (parsedResponse.error) {
    11 throw new Error(parsedResponse.error);
    12}
    13
    14return parsedResponse.isLoggedIn;
  3. Find the first uncommented review

    We now go to the “Reviews” section of the restaurant and extract the first uncommented review, then we generate a reply addressing any positive or negative aspect of the customer’s review.

    cli.ts
    1const review = await service.extractCustomerReview({ sessionId, windowId });

    Under the Hood

    facebook-commenter.service.ts
    1export const EXTRACT_REVIEW_PROMPT = `
    2 You are on the Sushi-Taco facebook's page. From the comments that customers left, find the first review that is uncommented and do the following:
    3 - Extract the review text.
    4 - Define if the review is positive or negative.
    5 - Generate a reply addressing this review.
    6`;
    7// ...
    8const promptContentResponse = await this.client.windows.pageQuery(sessionId, windowId, {
    9 prompt: EXTRACT_REVIEW_PROMPT,
    10 followPaginationLinks: false,
    11 configuration: {
    12 outputSchema: EXTRACT_REVIEW_OUTPUT_SCHEMA,
    13 }
    14});

    You should be able to see in the console the data extracted from the page and the generated reply in JSON format.

  4. Like and comment

    If the customer left a positive comment we order the agent to hit the like button, then we reply to the customer with the response previously generated.

    cli.ts
    1const { errors } = await service.replyToCustomer({ sessionId, windowId, review });
    2if (errors.length) {
    3 log.withError(errors).error("Unable to extract customer review");
    4 throw new Error("Unable to extract customer review", { cause: errors });
    5}

    Under the Hood

    facebook-commenter.service.ts - replyToCustomer
    1const beginOfComment = review.text.substring(0, 18); // this helps to identify the review
    2
    3// Like the comment if the review is positive
    4if (review.sentiment === "positive") {
    5 await this.client.windows.click(sessionId, windowId, {
    6 elementDescription: `The "Like" button near the comment that begins with "${beginOfComment}..."`,
    7 });
    8}
    9
    10// Replying to customer
    11 const result = await this.client.windows.type(sessionId, windowId, {
    12 elementDescription: `The comment box below the comment that begins with "${beginOfComment}..."`,
    13 text: review.reply,
    14 pressEnterKey: true, // Press Enter after typing
    15 });

    Learn more about clicking, typing, and hovering in Page Interactions.

  5. Clean Up

    Finally, the script terminates the session.

    cli.ts
    1await service.terminateSession(sessionAndWindow.session.id);
    facebook-commenter.service.ts - terminateSession
    1await this.client.sessions.terminate(sessionId);

Summary

This recipe shows how you can use Airtop to improve your customer relations by extracting relevant information and interacting with their reviews while saving time.

Built with