> ## Documentation Index
> Fetch the complete documentation index at: https://docs.visitoai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Book hairdresser appointments with Google Sheets

> Use Date and Time to check availability and record appointments. Two simple tabs, two actions, no slot IDs.

A customer chooses a haircut time, gives their name, and the agent records the appointment. Your spreadsheet automatically marks that time as unavailable.

This example is for **one barber, Diego, with one 30-minute appointment at each time**, in Mexico City time. You need only two tabs:

| Tab | Columns | What Visito can do |
| - | - | - |
| **Availability** | Date, Time, Available | Read |
| **Bookings** | Date, Time, Customer | Create rows |

**You do not need to make up slot IDs.** Select **Date and Time together** in the booking action's duplicate protection settings. Visito checks both values before adding a row.

## 1. Make the two tabs

Create a Google spreadsheet named **Hairdresser Demo — Availability and Bookings**. Rename its first tab **Availability**, and add a second tab named **Bookings**.

In **Availability**, put these headers in **A1:C1**:

```text theme={null}
Date	Time	Available
```

In **Bookings**, put these headers in **A1:C1**:

```text theme={null}
Date	Time	Customer
```

Leave Bookings empty below its headers. The agent will add a row after a customer confirms an appointment.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-bookings-empty.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=5da7ba1adb073b85a2f07ca4437970c6" alt="The Bookings tab starts with just Date, Time and Customer." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-bookings-empty.png" />

### Add your available times

In both tabs, select **A2:B1000 → Format → Number → Plain text** before entering dates and times. Use **YYYY-MM-DD** for dates and **HH:mm** for times. For example, `2026-10-05` and `10:00`. Keeping the same format in both tabs makes matching predictable.

Enter these rows in Availability. The last column will be a formula:

| Date | Time | Available |
| - | - | - |
| 2026-10-05 | 10:00 | 1 |
| 2026-10-05 | 10:30 | 1 |
| 2026-10-05 | 11:00 | 1 |
| 2026-10-05 | 11:30 | 1 |
| 2026-10-06 | 10:00 | 1 |
| 2026-10-06 | 10:30 | 1 |
| 2026-10-06 | 11:00 | 1 |
| 2026-10-06 | 11:30 | 1 |

Use future dates when trying this yourself. Each Date + Time pair must appear only once in Availability.

You can also paste the [availability template](/examples/google-sheets-hairdresser/availability.tsv) and [bookings headers](/examples/google-sheets-hairdresser/bookings.tsv) into A1 of their respective tabs. Create both tabs before pasting the availability formulas. Keep row 1 for headers, without merged cells or a title above them.

## 2. Let the sheet calculate availability

In **Availability!C2**, enter:

```excel theme={null}
=MAX(0,1-COUNTIFS(Bookings!A$2:A$1000,A2,Bookings!B$2:B$1000,B2))
```

Fill the formula down through C9. For each appointment, it counts booking rows with **both the same Date and the same Time**:

* No booking yet: **Available = 1**.
* A booking exists: **Available = 0**.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-availability-before.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=7bb5810cd20df4b2cca9250482339698" alt="Availability has only three columns; the formula checks Date and Time in Bookings." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-availability-before.png" />

The `$2:$1000` ranges stay fixed when you fill down. `A2` and `B2` change to the current row. If your sheet uses semicolons in formulas, replace the commas with semicolons.

Do not type over the Available formulas. The formula reduces availability; the action's duplicate check prevents Visito from adding the same Date + Time twice. No separate “decrease availability” action is necessary.

## 3. Make a test copy

In Google Sheets, use **File → Make a copy** and name it **Hairdresser Demo — TEST**. Copy both tabs, including their formulas, and leave its Bookings tab empty.

This must be a **separate spreadsheet file**, with the same headers and formats. Playground writes go to this copy. Keep the main file and test file clearly distinguishable in Google Picker.

## 4. Create “Check haircut availability”

Go to **Configuration → Actions → Google Sheets**. Connect your Google account in Integrations first if necessary; the spreadsheet selection happens inside the action.

1. Choose your Google connection.
2. Choose the main spreadsheet through **Choose spreadsheet** and Google Picker.
3. Select **Availability**.
4. Select **Date**, **Time** and **Available**, then continue.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-picker.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=90f82e2ec62fb49f5e16d087e296b14a" alt="Google Picker separates the main workbook from the test copy." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-picker.png" />

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-read-columns.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=7fb86e4b711009cda93c8bcd13c61bb4" alt="The main spreadsheet, Availability tab and three selected columns." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-read-columns.png" />

Set these permissions and types:

| Column | Read | Update | Create rows | Type |
| - | - | - | - | - |
| Date | On | Off | Off | Date |
| Time | On | Off | Off | Text |
| Available | On | Off | Off | Integer |

Available is detected as **Sheet-generated**. Its write controls are disabled.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-read-permissions.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=88d4738bf5a225e9542dc78bca19bb77" alt="Read-only permissions for all three availability columns." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-read-permissions.png" />

On the final step, name the action **Check haircut availability**. Choose the intended business scope and explain its purpose:

> Check available 30-minute men's haircuts with Diego in Mexico City time. Read before offering or booking an appointment. Offer only rows where Available is 1. Copy Date (YYYY-MM-DD) and Time (HH:mm) exactly from the chosen row to Book a haircut. Never invent appointments or prices. After a verified booking, read again to check that the chosen slot is now 0.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-read-purpose.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=3f57e27489822b9f77df657184cb6811" alt="A clear purpose tells the agent when to consult the sheet." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-read-purpose.png" />

Save the action. This action cannot see customer names because those belong to the other tab.

## 5. Create “Book a haircut”

Create a second Google Sheets action. Select the same main spreadsheet, the **Bookings** tab, and all three columns.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-booking-columns.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=e7925201a2d99e8c71cd66783aa2b113" alt="Select Date, Time and Customer in the Bookings tab." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-booking-columns.png" />

| Column | Read | Update | Create rows | Type |
| - | - | - | - | - |
| Date | Off | Off | On | Date |
| Time | Off | Off | On | Text |
| Customer | Off | Off | On | Text |

An empty tab may suggest Text for every column. Change Date to **Date** manually. Leave Read off so the agent cannot retrieve other customers' names.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-booking-permissions.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=83c4a577b32c82115a8378c2ef5e2984" alt="The booking action can create three values, with no read or update permissions." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-booking-permissions.png" />

On the final step:

1. Name it **Book a haircut**.
2. Under **Prevent duplicate rows**, select **Use existing columns together**.
3. Check **Date** and **Time**. Leave Customer unchecked: another name must not allow a second booking of the same time.
4. Date and Time become required automatically. Also mark **Customer** as required.
5. Choose **Hairdresser Demo — TEST → Bookings** as the test target.
6. Use the same business scope as the availability action.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-booking-unique-columns.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=c7dac04e8af9fad26597a9d94ada7fb3" alt="Date and Time together prevent duplicates; all three booking values are required." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-booking-unique-columns.png" />

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-test-target.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=03288c4a95b5162fa5b6bbf17d349fb6" alt="The booking action uses the separate TEST workbook in Playground." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-test-target.png" />

Use a purpose like this:

> Record one haircut only after the customer chooses a time and gives their name. First use Check haircut availability and require Available = 1. Copy Date and Time exactly from that available row. Customer is the supplied name. Ask only for missing customer information. After a verified write, say the appointment is recorded and check availability again. If that Date and Time already exist, offer another time. Never change values to bypass a conflict. Never retry an unverified write or claim it succeeded.

Save and review the mode. For the controlled Webchat test below, deliberately make **both actions Active** and use a disposable main workbook.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-actions-list.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=a99ebe9abb221dbfb4fa7ed86c09921d" alt="The two Google Sheets actions, with their separate operations." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-actions-list.png" />

## 6. Test the customer conversation

**Why Webchat for this example?** The read-only action uses the main file in Playground, while the booking action writes to the test file. Used together there, they would not demonstrate the main file's availability decreasing. Webchat with Active actions uses the main file for both.

Playground can execute Sheets actions. For an isolated end-to-end Playground test, configure a separate read action against the test dataset too. Do not point tests at real customer bookings.

Start a new Webchat conversation:

1. “I'd like a men's haircut with Diego on October 5, 2026. What morning times are available?”
2. “10:00 AM works for me. Can you book it?”
3. The agent should ask for your name **before writing**.
4. “My name is Alex Demo. Please book the 10:00 AM haircut with Diego on October 5.”

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-chat-name.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=8d98fb90cee4cf00a9efc3f821240335" alt="The agent checks availability and asks only for the missing name." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-chat-name.png" />

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-chat-booked.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=e827a8e823b2c5658e2e6630f7db3856" alt="The appointment is recorded after the action completes." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-chat-booked.png" />

Check both tabs, not just the reply. You should see exactly one row in Bookings and **0** for that appointment in Availability:

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-bookings-after.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=7630d02d647cd175c34ac42684f5df75" alt="One booking row with Date, Time and Customer, without an ID." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-bookings-after.png" />

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-availability-after.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=9b5685742dc1fdc27cd512178fa2c8b3" alt="The matching appointment changes from available to unavailable." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-availability-after.png" />

Then ask: “Could my friend Sam Demo also book that same 10:00 AM slot?” The agent should offer other times and leave the booking count unchanged.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-chat-occupied.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=3206fa19065889a3a6761bc7ac906177" alt="An occupied time is not offered again; other available times are suggested." width="1920" height="873" data-path="images/product-guide/en/sheets-simple-chat-occupied.png" />

The screenshots show a controlled local test. Its planner was disabled to isolate tool execution; this is not a customer setup step or proof that production routing has been tested. A handoff may occur before the response agent receives its tools.

## 7. Inspect what happened

Open **Actions → History** and filter by **Book a haircut**. Open the test execution. Check **Live**, **Completed**, and **Spreadsheet changes verified**.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-history.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=ebcc613027fd5909edb2b00bd028507b" alt="The booking execution in Actions history." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-history.png" />

Open its details and inspect the submitted values and result. The request contains Date, Time and Customer through their internal column keys; no customer-supplied slot ID is needed. A verified result means the changed cells were read back successfully. It does not confirm a payment or a reservation in another booking system.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-execution.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=6bc138a416ab4710539a671939c77b56" alt="Submitted values and the verified execution result." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-execution.png" />

Use **Open conversation** to see the customer's request, the agent's reply and action activity together. Open the booking action's details there to connect the execution to the message that triggered it.

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-conversation.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=81724f0dfdc9a465dc44975656f160f4" alt="Conversation detail links the request and completed action." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-conversation.png" />

<img src="https://mintcdn.com/muhammadtest/nStPtyl8oIGuFGuS/images/product-guide/en/sheets-simple-conversation-execution.png?fit=max&auto=format&n=nStPtyl8oIGuFGuS&q=85&s=c6d2b6ba8ab4c87caaa29f4238e58143" alt="The same booking execution viewed from the conversation." width="1512" height="772" data-path="images/product-guide/en/sheets-simple-conversation-execution.png" />

The local sidebar shows a separate information-panel timeout in these screenshots. The booking itself is verified in the expanded message receipt and Actions history. A Google Sheets appointment does not create a reservation in Visito Commerce.

## Keep the sheet simple and reliable

* **Add another day:** add new Date and Time rows to Availability and fill down the formula. You do not need to create IDs or update a list of permitted slot IDs.
* **Use consistent times:** `10:00` and `10 AM` are different text values. The agent should copy the sheet's values exactly.
* **Reset a disposable demo:** clear the test booking row's values in Bookings, keeping the headers. Availability returns to 1. Do not erase real bookings to reset a test.
* **More barbers:** add a Barber column in both tabs, include it in the formula and select Date + Time + Barber as unique together. Date + Time alone represents one appointment across the whole tab.
* **Do not enable Update on the unique columns.** This example does not implement rescheduling, cancellations, payments or multiple places per time.

<Warning>
  The uniqueness rule blocks a duplicate combination within Visito writes. It does not validate that a new Date + Time exists in another tab, prevent someone from editing Google Sheets manually, or make this a full scheduling system. Keep the availability-check instructions, review your business rules, and never automatically retry an unverified write.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.