Skip to content

Commit

Permalink
📝 Add 'WhatsApp business API pricing' blog post (#1858)
Browse files Browse the repository at this point in the history
Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
  • Loading branch information
younesbenallal and baptisteArno authored Oct 25, 2024
1 parent 2fe1c31 commit 14833d5
Show file tree
Hide file tree
Showing 9 changed files with 671 additions and 5 deletions.
2 changes: 2 additions & 0 deletions apps/docs/contribute/guides/blog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ By default the og image is generated from the title of the blog post. If you wan

All images need to be placed under the `public/images/blog/<POST_FILENAME>` folder where `<POST_FILENAME>` is the name of the mdx file you are creating/editing. The image file name should be in lowercase and separated by `-`. It is best if the image width is no more than 800px.

All links to other blog posts should look like `/blog/<POST_SLUG>`.

Here are all the components you can use in your blog post:

- `Image`: To display an image. `width` and `height` props are required and must match the actual size of the image. Example: `<Image src="/images/blog/my-awesome-blog-post/image.jpg" alt="My awesome image" width={800} height={600} />`
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ A chatbot's success hinges on engaging your users. Here are some strategies to m
- **Quick Replies**: Speed up conversations with buttons for common responses, actions, or links. This reduces friction and keeps users engaged.
- **Interactive Elements**: Incorporate images, GIFs, or short videos to liven up your chatbot’s responses and retain user interest.

More strategies in our [chatbot best practices guide](/chatbot-best-practices).
More strategies in our [chatbot best practices guide](/blog/chatbot-best-practices).

**Common Pitfalls to Avoid**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,6 @@ Crafting powerful **chatbot scripts** requires understanding your audience, clea

From **sales-boosting conversations** to efficient customer support interactions, well-designed scripts can enhance user engagement and drive business results.

By leveraging tools like Typebot and AI assistants, and following [best practices](/chatbot-best-practices) for natural, personalized conversations, you can create chatbot experiences that meet user needs and leave a lasting positive impression of your brand.
By leveraging tools like Typebot and AI assistants, and following [best practices](/blog/chatbot-best-practices) for natural, personalized conversations, you can create chatbot experiences that meet user needs and leave a lasting positive impression of your brand.

<Cta />
10 changes: 8 additions & 2 deletions apps/landing-page/src/app/blog/create-whatsapp-chatbot/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Engage your audience with:

<Callout status="info" title="Info">
If you need inspiration, we gathered some [chatbot script
exampes](https://typebot.io/blog/chatbot-script-examples) to help you get
exampes](/blog/chatbot-script-examples) to help you get
started. There are best practices, tips, and prompts to help you create a
successful chatbot.
</Callout>
Expand Down Expand Up @@ -214,9 +214,15 @@ Once published, share the designated WhatsApp number or group link with your cus

Remember, even after publishing, continue monitoring your chatbot's performance, gathering user feedback, and making ongoing improvements. This ensures a consistently engaging and valuable experience.

<Callout status="info" title="Info">
Did you know that WhatsApp charges for each conversation window? We've put
together a [WhatsApp pricing calculator](/blog/whatsapp-business-api-pricing)
to help you estimate the cost of your WhatsApp chatbot.
</Callout>

## Designing an Engaging WhatsApp Chatbot Experience

Now that you've set up the technical foundation for your WhatsApp chatbot, it's time to focus on crafting an engaging and memorable experience for your users. Here are some [best practices](/chatbot-best-practices) and strategies to consider:
Now that you've set up the technical foundation for your WhatsApp chatbot, it's time to focus on crafting an engaging and memorable experience for your users. Here are some [best practices](/blog/chatbot-best-practices) and strategies to consider:

### Best Practices for Conversational Design

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ In our case we will keep the initial flow simple. The real magic happens when we
- Offer easy outs: Always give users a way to start over or end the conversation.
- Use visuals: Typebot lets you add images. Use them to showcase products or add some personality to your bot.

More strategies in our [chatbot best practices guide](/chatbot-best-practices).
More strategies in our [chatbot best practices guide](/blog/chatbot-best-practices).

### Setting the Current Product in a Variable

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"use client";

import {
Box,
Flex,
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
Select,
Text,
VStack,
} from "@chakra-ui/react";
import { isNotDefined } from "@typebot.io/lib/utils";
import type React from "react";
import { type ChangeEvent, useState } from "react";
import { pricingData } from "./pricingData";

const messageTypes = [
"Marketing",
"Utility",
"Authentication",
"Service",
] as const;

export const WhatsAppPricingCalculator = () => {
const [selectedCountry, setSelectedCountry] =
useState<(typeof pricingData)["markets"][number]["market"]>();
const [selectedMessageType, setSelectedMessageType] =
useState<(typeof messageTypes)[number]>();
const [messageCount, setMessageCount] = useState(1);
const [price, setPrice] = useState<number>();

const updatePrice = () => {
if (isNotDefined(selectedCountry) || isNotDefined(selectedMessageType))
return;

const countryData = pricingData.markets.find(
(market) => market.market === selectedCountry,
);
if (!countryData) return;

const typePrice =
countryData[
selectedMessageType.toLowerCase() as keyof typeof countryData
];
setPrice(
typeof typePrice === "number" ? typePrice * messageCount : undefined,
);
};

const updateCountry = (event: ChangeEvent<HTMLSelectElement>) => {
setSelectedCountry(
event.target.value as (typeof pricingData)["markets"][number]["market"],
);
updatePrice();
};

const updateMessageType = (event: ChangeEvent<HTMLSelectElement>) => {
setSelectedMessageType(event.target.value as (typeof messageTypes)[number]);
updatePrice();
};

const updateMessageCount = (_: string, value: number) => {
setMessageCount(Math.max(1, value));
updatePrice();
};

return (
<Box bg="gray.800" p={6} borderRadius="lg" shadow="xl">
<VStack spacing={6} align="stretch">
<Box>
<Text mb={2} fontWeight="medium">
Select Country:
</Text>
<Select
value={selectedCountry}
onChange={updateCountry}
placeholder="Select a country"
>
{pricingData.markets.map((market) => (
<option key={market.market} value={market.market}>
{market.market}
</option>
))}
</Select>
</Box>
<Box>
<Text mb={2} fontWeight="medium">
Select Message Type:
</Text>
<Select
value={selectedMessageType}
onChange={updateMessageType}
placeholder="Select a type"
>
{messageTypes.map((type) => (
<option key={type} value={type}>
{type}
</option>
))}
</Select>
</Box>
<Box>
<Text mb={2} fontWeight="medium">
Number of Messages (optional):
</Text>
<NumberInput
value={messageCount}
onChange={updateMessageCount}
min={1}
step={100}
clampValueOnBlur={true}
>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</Box>
{price && (
<Flex justify="space-between" align="center" mt={4}>
<Text fontWeight="bold">Estimated Price:</Text>
<Text fontSize="xl" fontWeight="bold" color="blue.300">
{new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 4,
maximumFractionDigits: 4,
}).format(price)}
</Text>
</Flex>
)}
</VStack>
</Box>
);
};
Loading

0 comments on commit 14833d5

Please sign in to comment.