# Quick Start

With Billflow you can create billing pages that connect your app to your Stripe account.

![](/files/-MQmZCp3u79_uwRrtZ0J)

## What is Billflow?

Billflow was built to make starting and scaling a subscription based business easier than ever. Billflow provides a user interface (UI) on top of Stripe. Stripe will remain the single source of truth for all things billing which makes Billflow the easiest & fastest way to launch with Stripe. Today, Billflow offers 5 types of billing pages. **Plan Picker**, **Checkout Form**, **Customer Portal**, **Pricing Page**, and **Invoice Portal**.

If you haven't created your Stripe & Billflow accounts yet, go ahead and create your **free** [Stripe account](https://dashboard.stripe.com/register) & [Billflow account](https://dashboard.servicebot.io).

## First time setting up Billflow?

Start by following these steps for [First Time Setup](/setup/first-time-setup)

## Popular How To's

{% content-ref url="/pages/-MGTNzO0-KtmaPdRTBfw" %}
[Setup Pricing](/how-to/setup-pricing)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTQwVN9cxVxBD8FgtP" %}
[Connect to SaaS](/how-to/connect-to-saas)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp-oZor2dYPZ\_\_sKRL" %}
[Change Style](/how-to/change-style)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTT9m7Y\_ZAsniwFE3J" %}
[No-code App Builders](/no-code-integrations/no-code-app-builders)
{% endcontent-ref %}

## Popular FAQs

* [Is Billflow GDPR compliant?](/help/frequently-asked-questions#is-servicebot-gdpr-compliant)
* [How to setup my Stripe to work with Billflow?](/setup/first-time-setup/connect-and-setup-stripe)
* [I have finished setting up, how do I go live?](/setup/first-time-setup/activate-live-payments)
* [Can I use the Customer Portal for my existing Stripe customers?](/help/frequently-asked-questions#can-i-use-the-customer-portal-for-my-existing-stripe-customers)
* [How do I enable coupon?](/how-to/use-coupons)
* [How to I setup taxes?](/how-to/taxes)
* [How can I update my prices and add new plans?](/how-to/update-pricing#update-a-price)

## Roadmap

Check out [this link](https://app.getacute.io/v/servicebot/) to request features and see where the product is going.

## Pricing Model Library

Looking for some pricing model and style inspiration? Check out the [**pricing model library** ](https://www.billflow.io/pricing-models)and [**style templates**](https://codepen.io/collection/JGjjwo?grid_type=grid\&cursor=ZD0wJm89MCZwPTEmdj00) we've built out 👇

<div align="left"><img src="/files/-MknKNIWqGlZiMDkZbDN" alt="Visit: https://www.billflow.io/pricing-models"></div>

<div align="left"><img src="/files/-MknKXVqIphkTmkURzFB" alt="Visit: https://codepen.io/collection/JGjjwo"></div>


# First Time Setup

Step by step guide to getting Billflow Setup

![](/files/-MQmMPRY3pdUcuxJcWsl)

You can be up and running with Billflow in a matter of minutes. The following is a step by step guide to get you from signup up, to taking live payments from customers.

## Step 1: Connect & Setup Stripe

{% content-ref url="/pages/-MGTJy3OEvkjsZ54KeUJ" %}
[Connect & Setup Stripe](/setup/first-time-setup/connect-and-setup-stripe)
{% endcontent-ref %}

## Step 2: Invite Team Members

{% content-ref url="/pages/-MGTKeFNI\_oMOeyun3Y7" %}
[Invite Team Members](/setup/first-time-setup/invite-team-members)
{% endcontent-ref %}

## Step 3: Create Your First Billing Page

{% content-ref url="/pages/-MGTKTHzGPAucE\_2s9dP" %}
[Create Your First Billing Page](/setup/first-time-setup/create-your-first-billing-page)
{% endcontent-ref %}

## Step 4: Embed The Billing Page

{% content-ref url="/pages/-MGTKZq4iPmsV8JbuqcM" %}
[Embed The Billing Page](/setup/first-time-setup/embed-the-billing-page)
{% endcontent-ref %}

## Step 5: Activate Live Payments

{% content-ref url="/pages/-MGTKb8Y8sKP8OPJioxt" %}
[Activate Live Payments](/setup/first-time-setup/activate-live-payments)
{% endcontent-ref %}


# Connect & Setup Stripe

Connect Billflow to your Stripe account & setup

## Connect to Stripe

If you have not connected to Stripe during signup, you can do so now on the Dashboard.

![](/files/-MQUBdCDg88v63wRs0JN)

{% hint style="info" %}
Currently you must have a fully complete Stripe account with bank details in order to connect to Billflow. If you wish to test around, check out our [examples page](https://dashboard.servicebot.io/examples) to see how the billing pages look and how they are installed.&#x20;
{% endhint %}

Now Billflow is connected to your Stripe account, let's set up your pricing

## Test Mode/Live Mode

An important concept to understand is that both Stripe & Billflow have a 'Test Mode' and 'Live Mode'. Test Mode allows you to build out an entire integration and test the end-to-end process with fake payments using test CC information. When you're ready to take real payments, you can change your integration to Live Mode.&#x20;

![Test/Live Mode on Stripe Dashboard](/files/-MIKhT9kaCS1q_hdFVOs)

Start by performing the following steps in Test Mode, and things can  easily be promoted to Live Mode.

## Setup Stripe

In order to start taking payments, Products & Prices must first be created in Stripe.&#x20;

If you already have Products in Stripe, and you only plan to use the **Invoice Portal** or **Customer Portal with no Change Plan** **functionality**, you can skip this section.

For a detailed process with specific pricing model examples, you can learn more [here](/how-to/setup-pricing).&#x20;

### Step 1: Pricing Model

Determine how many tiers are going to be in your Product/Service offering, whether there is a free trial, and what the cost of each tier is. The following structure allows for very complex pricing including metered billing and combinations of pricing strategies. Once you know what you're going for, you can go to Step 2.

In the following example we will create two tiers for a SaaS application, SampleSaaS. The 'Basic' tier will be $10/mo and the 'Pro' tier will be $50/mo.

![](/files/-MQUBjmMPsz89N7P6WiR)

### Step 2: Create Products & Prices in Stripe

Stripe has an object called a 'Product'. You can create Products from the Stripe Dashboard. Products contain another object called 'Prices'. Products can contain multiple Prices.

The simple rules to creating your pricing model are as follows:

**Create a Product for every tier and/or ‘metric’ you may have.**&#x20;

Based on our example, we will create two Products in Stripe, each with a single Price. One for our Basic tier, and one for the Pro.

Select Products and "+ Add Product" for each.

Fill in a name and give the Pricing information, then Save Product.

![Stripe Product for the Basic Tier](/files/-MIKi1UWJ6lfsIG03oP5)

![Stripe Product for the Pro Tier](/files/-MIKi9DomvthPm0HJzQD)

### Step 3: Add Metadata

Lastly, we will add Metadata to the Stripe products you created. This metadata will tell Billflow which of your Stripe Products are part of your Service Offering, and what the tiers look like.

Every Product in your service offering will have two metadata tags, 'sb\_service' and 'sb\_tier'. Every Product will have the same value for 'sb\_service' which will be the name of your service. Then, each Product corresponding to a tier will have the 'sb\_tier' be name of the tier.&#x20;

From our example we will give each product the 'sb\_service' value of 'SampleSaaS'. And we will give the Basic tier an sb\_tier value of 'Basic', and the Pro tier an 'sb\_tier' value of 'Pro'.

Select each Product created before, and click 'Edit metadata'.

![Metadata for SimpleSaaS Basic Product](/files/-MIKiJR2Ty5U5BtlmJ37)

![Metadata for SimpleSaaS Pro Product](/files/-MIKiP608LUBXYAGtUnx)

Now our Stripe account is ready to go,  for detailed examples of specific pricing model examples, you can learn more [here](/how-to/setup-pricing).&#x20;

Next step is to invite team members.


# Invite Team Members

Invite your team members to Billflow

If you have any team members that would like to create billing pages or assist with the installation, now is the best time to add them. Select **Team** on the side bar navigation on the dashboard to manage your team members. Then select **+ Add New Team Member**.&#x20;

Enter their **Name**, **Email**, **Role**, and select **Invite**.

There are two sets of permissions that can be granted to an invited member. The first is Admin which is able to access the ‘account’ section and the other is Non-Admin who have access to everything but the ‘account’ section. As this is separate from Stripe, your team members won’t have access to the Stripe account-- although linking them  may be useful.

![](/files/-MQUC3YtboBDKGR3FBiZ)


# Create Your First Billing Page

Create your first Billing Page in Billflow

Now we're ready to create our first billing page. Which billing page you use is determined by your usecases and where you'd like to have the billing page reside. Below is a short description of each:

![](/files/-MIKj3hX_vXiRv63Ap2I)

## Step 1: Select your page type

From the Billflow dashboard, select the billing page type for your needs and Create Now.

For this example we will continue building a Customer Portal for SimpleSaaS.

![](/files/-MQUCDpvbX86nlmtGR8E)

## Step 2: Configure your Page

Start by giving your billing page a descriptive name about the product its used for, when it was created, or a version number.

![Billing Page Named & In Test Mode](/files/-MIKjSb33qmJpRhyJSUg)

{% hint style="warning" %}
You will notice our billing page is starting out in 'Test Mode' which maps directly to Stripe's Test Mode. It is best practice to create your first pages in Test mode and they can easily be promoted to Live Mode for real payments.
{% endhint %}

The sections that appear will vary based on billing page selected and features being used. In the example of the customer portal we are creating, we will next see options for how the billing page should look and behave. Now is when we can decide things like whether we want to offer coupons and the cancellation behavior. On the right there is a live preview of an example of what the customer would see.&#x20;

For a detailed breakdown of the usecases, features, and options of each billing page, read along here:

{% content-ref url="/pages/-MGThtIVXXX7bPPpNIzn" %}
[Plan Picker](/billing-pages/plan-picker)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTi5VCJ3Jlw2v-LgIc" %}
[Customer Portal](/billing-pages/customer-portal)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTi2INq5nRltmKIukm" %}
[Checkout Form](/billing-pages/checkout-form)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp-BCnyC2J3H4eYNDY" %}
[Pricing Page](/billing-pages/pricing-page)
{% endcontent-ref %}

{% content-ref url="/pages/-MHGeqPjbo9ZtJ7\_nC0a" %}
[Invoice Portal](/billing-pages/invoice-portal)
{% endcontent-ref %}

Next section is the Stripe Services & Product Setup. We already setup our Products and Service in an earlier step so we should see the option to SimpleSaaS. Make sure you are creating your billing page in the same mode, Test/Live, that you created your Service in Stripe. For detailed instructions on configuring your Services & Product you can read more [here](/how-to/setup-pricing).

The next section is Language. The default behavior is to detect your user's browser setting and display their preferred language. We can override with a default language, and we can also provide custom translations.&#x20;

Next we have Advanced settings for developers. This provides useful settings to run custom code on events that happen from the billing pages and do more in-depth debugging

Lastly, we can embed our billing page. Click 'Save Now' and continue to the next Guide.


# Embed The Billing Page

Add the billing page to your website or app

In the embed section you will see many options to install your billing page on. Billflow provides plugins to popular platforms that make installation very easy. Not only do these plugins make it easy to embed, but it also has the integration with the platforms user accounts done for you. If you do not see your platform listed or you have a custom application, Billflow is made for that too.&#x20;

## Custom Code

You can copy and paste the HTML snippet provided from the dashboard. The snippet always contains the Billflow ID and Billing Page ID. For the Customer portal and Invoice portal, the Email or Stripe Customer ID will be there so you can dynamically pass that in. For more detailed options and samples of specific frameworks check out the link below

{% content-ref url="/pages/-MGTTBFEYHMQkJZ7W9p6" %}
[Languages & Frameworks](/developers/languages-and-frameworks)
{% endcontent-ref %}

## Platforms

If you select the platform your site or app is running on, the dashboard will provide you with links to the plugin used on the platform. It will also provide you snippets to be used within the plugin. For detailed instructions and features available on the plugins, continue below.

{% content-ref url="/pages/-MGTTFN1Y1ptcNE6YYvj" %}
[Bubble](/no-code-integrations/no-code-app-builders/bubble)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTI8\_MPZ4mQAceQaf" %}
[Webflow](/no-code-integrations/no-code-app-builders/webflow)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTKMxtuPdZ2LBxwSa" %}
[WordPress](/no-code-integrations/no-code-app-builders/wordpress)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTNWH\_3Wo7uOWC7Wo" %}
[Drupal](/no-code-integrations/no-code-app-builders/drupal)
{% endcontent-ref %}

Now we are embedded and have tested the integration, we are ready to go live!


# Activate Live Payments

Enable Billing page for real payments

It's time to take our test billing pages and start using them for real payments!

## Go Live

Toggle the Test/Live mode switch to take the billing page live.&#x20;

Select the Billing page you wish to take live. Switch the toggle on the top right of the page from Test Mode to Live Mode. If your billing page uses Stripe Products and they do not exist in Live Mode, it will offer to copy the Test Mode Products to Live Mode for you. You can optionally Copy over the Products to Live mode directly in Stripe.

![Switch billing page live](/files/-MIKjuPtebg25zzsOIRZ)

If you have not already subscribed, a pop up will appear asking you to subscribe. You must subscribe to create a Live Mode billing page.&#x20;

![Upgrade Account](/files/-MIa4B7tXW1UF1E_5zgj)

You need to have Stripe Products in both Test and Live mode in order to have billing pages in both modes. Billflow can automatically create those for you in live mode. They can also be added directly in Stripe, just ensure that the appropriate metadata described in earlier steps is added.&#x20;

## Multiple Environments Process

Do you have multiple environments and want to have a billing page for your development/test environment and one for production? Follow along below for the best practice.&#x20;

### Step 1: Duplicate Billing Page

Click the option menu on the billing page that has been created, then select Duplicate Page

![Duplicate a billing page](/files/-MIa3fMpRETLwqcFwV-G)

Name it something descriptive to your environment, like 'Live' or 'Prod' ... then click Duplicate

![Naming Billing Page](/files/-MIKkIpMvmuUuuOIEler)

### Step 2: Switch to Live mode

Next we can toggle the Test/Live mode switch to take the billing page live.&#x20;

![Switch billing page live](/files/-MIKkVU-f4O9yc22qSTG)

If you have not already subscribed, a pop up will appear asking you to subscribe. You must subscribe to create a Live Mode billing page.&#x20;

![Upgrade Account](/files/-MIa4B7tXW1UF1E_5zgj)

You need to have Stripe Products in both Test and Live mode in order to have billing pages in both modes. Billflow can automatically create those for you in live mode. They can also be added directly in Stripe, just ensure that the appropriate metadata described in earlier steps is added.&#x20;

### Step 3: Embed Live Mode Page

Now we are ready to embed the live mode page. If you have separate environments for development and production. You will just use the Billing Page ID of the Live Mode page in your production. If you have a single environment, simply embed the appropriate snippet again with the one provided from the newly created billing page. Or, you can just change the billing page ID to point to the new one.

## Done!

You are now ready to use Billflow with real customers and real $$!

Continue on to learn more about the features available to each page and how to get the most out of your Billflow account.


# Plan Picker

Plan Picker Overview, Features, & How-To's

![](/files/-MQmeQR_iC4kp9Hdxu0l)

## Overview

The Billflow Plan Picker allows you to easily show your product pricing in your app, let users checkout,  see what plan they're on, and change their plan. Because it's connected directly to your Stripe account, you never have to worry about updating your website when you change your pricing.

You have the option to show subscribers the current plan they are on, or automatically show the Customer Portal.

The Plan Picker has a simple HTML/Javascript embed so it can be embedded onto any website that will accept this common embed method. It authorizes users with a security hash generated with the logged-in user's email or Stripe Customer ID. This method of authorization allows Billflow to work with any authentication provider. Make sure to check out plugins to make integration easier.

## Select a Service

A Service is a collection of Stripe Products & Prices that make up the tiers & intervals of a service offering. If you have not created a service already, you will have the option to create a 'demo' service. To learn how to create your own service and specific pricing model, [real along here](/how-to/setup-pricing).&#x20;

Select the service you wish to create a Plan Picker for.

{% hint style="info" %}
Not seeing a service listed that you created in Stripe? Make sure you have that service in the same mode (Test or Live) that your billing page is in.&#x20;
{% endhint %}

## Plan Picker Settings

Following are the options available on the Plan Picker

### **Show Customer Portal for Subscribers**

The Plan Picker will always show plans to unsubscribed users. If a customer is subscribes, you have the option to then show them the Plan Picker with their selected plan, or to show the Customer Portal. If you are looking to have a distinct plan selection page, leave this option off. If you'd like to have an all-in-one page for subscribing and viewing billing information, turn this option on. Commonly used for Freemium models.

### Hide Tiers

Want to hide a certain tier that's only available to a certain group or an a certain time? Use hide tiers to select from your available tiers and users will not see it as an option.

### Disable Tiers

Want to disable certain tiers to run a promotion of things to come? Use disable tiers to select from your available tiers and users will see that tier greyed and unavailable now.

### Charge plan change immediately

Use this option to charge a plan change immediately instead of prorating the difference on the current billing cycle. This will set the billing cycle anchor date to the date of the plan change.

### Show monthly rate on Annual plans

Turn this option on to show how much the annual plans cost as a monthly rate. Eg: A $120/yr plan would show $10/mo billed annual

### Show discount on Annual plans

Turn this option on to show a discounted flag on the annual plans.

### Show all interval plan on the same page

This option will show all plans in the configured service together as opposed to showing only plans in a given interval with an interval toggle.

### Hide the interval selector

This option will hide the interval toggle and show only the plans in the default interval. This can be used if you want to show only monthly plans on one page, and only annual on another.

### Interval selector alignment

Choose the alignment of the interval toggle, left, right, or center.

### Default Interval

Select a billing interval to be the default.&#x20;

### Custom Interval

Only use this option if you want to change the default interval and you have a custom interval like "Every 3 months" or "Every 6 weeks". The value will just be the number in your interval.

### Pre-applied Coupon

Fill this option in with a Stripe Coupon ID or Promo Code to have a coupon automatically applied to any tier chosen. Useful feature for running a promotion on a specific URL.&#x20;

### How to Identify Customers

You must choose how you will identify customers. You have an option to pass in a customer's **email** address or their **Stripe Customer ID** in order for Billflow to look up their information in Stripe.&#x20;

Identifying with email is simpler as it requires less data to store. Identifying with Stripe Customer ID is more robust because you do not need to handle email changes and is also needed when doing a tenant based architecture where multiple account are under the same group.

### Enable Security Hash

Turn on to enable security on your page in test mode. This option is required in live mode. In order for the customer portal to securely display customer billing information, a hash must be passed to the billing page options. This hash must be generated on the server with the logged in user's email or Stripe customer ID, whichever you are using to identify users. This step is covered in more detail in the [Secure Setup](/billing-pages/plan-picker#authentication-secure-setup).

## Customer Portal Settings

If you enabled "**Show Customer Portal for Subscribers**" you will see Customer Portal Settings. To learn about the options available to it or about embedding a separate Customer Portal page, check out the [Customer Portal](/billing-pages/customer-portal#customer-portal-settings).

## Checkout Form Settings

When a user selects a plan before they have subscribed, it will automatically go to the correct Checkout Form for that tier. To learn more about the options available on it or about embedding a separate Checkout Form, check out the [Checkout Form](/billing-pages/checkout-form#checkout-form-settings).&#x20;

## Language Settings

All Billflow billing pages have the ability to automatically detect the customer's browser language preference and translate the billing page accordingly. If the language is not supported by our page, a default language will be displayed. The default language is English US.

### Automatically Detect User's Browser Settings

Turn on to automatically detect the customer's browser settings and translate the page. If not enabled, select your default language. Not seeing a language you need there? Contact us on the chat to request a translation.

### Add a Custom Resource

Turn this option on to pass in your own translations. This can be used to host your own language files, but can also be used to change the text of specific sections to your desired text. To learn more about this option, read along [here](/how-to/internationalization/support-multiple-languages#resources).&#x20;

## Advanced Settings

### Enable Handle Response&#x20;

Turn on to enable the handleResponse function. The function is used to handle events with custom code when events happen on the billing page like button clicks and actions performed. To learn more about events available and sample code snippets, read along [here](/developers/handling-embed-events).&#x20;

### Debug Mode

Turn on to enable debug mode for extra console logging.

## Embed

Embedding the Plan Picker is a two-step process. For the client side installation just copy and paste the provided HTML snippet. The next step is secure setup.

If you have a frontend framework, check out the [samples](/developers/languages-and-frameworks) of embedding with those.

## Authentication Secure Setup

The customer portal must be behind some kind of user authentication in order to safely show customers their billing information. Billflow authenticates users with an HMAC hash generated for the logged-in user, this allow is to work with any authentication system. If you are using a No-code platform, make sure to check out our plugins as they handle this step for you. If you are integrating into a custom application, continue on.

Your code to generate an HMAC for your app must be placed in the back-end of your application. Grab the snippet from the dashboard to add to your server. You may generate the HMAC with the user's **email** OR the user's **Stripe Customer ID** (customer\_id).

The HMAC generated will be passed to the client-side snippet to a property called 'hash'.

{% hint style="info" %}
Don't see your server-side language listed? Let us know and we'll get a code snippet for you!
{% endhint %}

{% tabs %}
{% tab title="Node.js" %}

```javascript
const crypto = require("crypto");
const email_hash = crypto.createHmac(
    "sha256",
    "YOUR_SECRET_KEY" // SECRET KEY (KEEP SAFE!)
).update(req.user.email).digest("hex") // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Rails (Ruby)" %}

```ruby
email_hash = OpenSSL::HMAC.hexdigest(
    'sha256', # HASH FUNCTION
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    current_user.email # REPLACE WITH USER'S EMAIL ADDRESS
) # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Django (Python)" %}

```python
import hmac
import hashlib

email_hash = hmac.new(
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    request.user.email, # REPLACE WITH USER'S EMAIL ADDRESS
    digestmod=hashlib.sha256 # HASH FUNCTION
).hexdigest() # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="PHP" %}

```php
$email_hash = hash_hmac(
    'sha256', // HASH FUNCTION
    $user->email, // REPLACE WITH USER'S EMAIL ADDRESS
    'YOUR_SECRET_KEY' // SECRET KEY (KEEP SAFE!)
); // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Other" %}
Generate an HMAC with SHA256 whenever a user logs into your app. Most web frameworks will have a method or library to help you do this. You'll need your app’s secret key and the email or user\_id of the currently logged-in user.

Secret Key\
[**Get Your Secret Key**](https://dashboard.servicebot.io/billing-embed)
{% endtab %}
{% endtabs %}

Seeing 403s? You can verify your HMAC is being generated properly by creating one [here](https://www.freeformatter.com/hmac-generator.html). Use "SHA256", pass in the customer's email or customer ID, and use your Billflow secret key as the secret. Compare that with what you're generating server-side and what's being passed to the client-side.

{% hint style="warning" %}
**Keep your secret key safe!** Never commit it directly a public repository, client-side code, or anywhere a third party can find it.
{% endhint %}

{% hint style="info" %}
Don't forget to check out our [integration samples](/developers/languages-and-frameworks)!
{% endhint %}

## Change Tier and Plan Order

You can modify the order that tiers appear from their default ordering by price. Metadata tags are used in Stripe to do this, add these to your Stripe Product.

| Metadata Key             | Description                                                                                                              | Example Values |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------ | -------------- |
| sb\_pricing\_tier\_order | Add this metadata property to a Stripe Product. The lowest value tier appears left-most on your Pricing page.            | 1              |
| sb\_pricing\_plan\_order | Add this metadata property to a Stripe Plan. The lowest value plan appears higher on a tier with multiple pricing plans. | 5              |

## Popular How-to's

{% content-ref url="/pages/-MGp-uhmJJtALiI7giMf" %}
[Plan Picker Style Templates](/how-to/change-style/plan-picker-style-templates)
{% endcontent-ref %}

## Developers

The pricing page has many more powerful features that can be unlocked with some simple coding. Check out the developer docs to learn more.

{% content-ref url="/pages/-MGTmTB\_dnRVUsObnb\_g" %}
[Embed Configurations](/developers/embed-configurations)
{% endcontent-ref %}


# Checkout Form

Checkout Form Overview, Features, & How-To's

![](/files/-MQmeh_SIjeXSkaPD4zL)

## Overview

The Billflow Checkout Form allows you to easily embed a payment form anywhere you need.  Because it's connected directly to your Stripe account, you'll never have to worry about updating your website when you change your pricing.

You can customize the fields they need to enter, take payment for subscriptions or one-time payments, and automatically redirect to a page of your choosing.&#x20;

The Checkout Form has a simple HTML/Javascript embed so it can be embedded into any website that will accept this common embed method.

## Select a Service

A Service is a collection of Stripe Products & Prices that make up the tiers & intervals of a service offering. If you have not created a service already, you will have the option to create a 'demo' service. To learn how to create your own service and specific pricing model, continue reading[ here](/how-to/setup-pricing).&#x20;

Select the service you wish to create a Pricing Page for.

{% hint style="info" %}
Not seeing a service listed that you created in Stripe? Make sure you have that service in the same mode (Test or Live) as your billing page is in.&#x20;
{% endhint %}

## Choose a Tier & Interval

### Checkout tier

Select the tier that the checkout form should be for.

### Checkout interval

Select the billing interval that the checkout form should be for.

## Checkout Form Settings

### Checkout Layout

Choose to show the default horizontal checkout or a side-by-side checkout. Select one to see a preview of it.

### Enable Product Image

Show the image configured on the Stripe product in the checkout form. If there is multiple products in the same plan, it will choose the image from the first line item.

### Password

Turn on to request asking for a password. The password will be available in the handleResponse payload.

### Custom Fields

Use the custom fields section to gather non-payment related information from your customers. You can assign a label and whether the field is required or not. This information will be available in the [handleResponse](/developers/handling-embed-events#handling-actions) function and is added to the Customer & Subscription metadata in Stripe. If a field is added for "Business Name?" for example, the metadata key "bf\_cf\_business\_name" will be added to the Stripe Customer & Subscription with the value your customer entered on checkout.

### Enable Coupon

Turn on to enable a button for users to add coupon codes. Coupons are created from the Stripe dashboard, to learn more about using coupons read along [here](/how-to/use-coupons).

### Require Card on Signup

Turn this option on to always force a customer to enter their Credit Card information. By default, payment information will not be requested if a tier is free or has a free trial.&#x20;

### Use Stripe Styling

Turn this option on to use the default Stripe element styling. This only affects the Credit Card information field. You can fill the section with a Stripe Element style object exactly the same as how [Stripe works](https://stripe.com/docs/js/appendix/style). For an example, [check this out](https://codepen.io/kmidkiff/pen/RwGREzE).

### Name on Card

Turn on to ask for Name in the Billing Information Section.

### Billing Address Fields

Turn on Address fields to appear in the Billing Information section.&#x20;

### Enable Shipping Address Fields

Turn on to enable shipping fields, and select each field to appear in the Shipping Information section.

### Terms & Conditions

Turn on to show a required Terms & Conditions checkbox on checkout. Once on you can configure the label, the link to your Terms & Conditions document, and the error if not checked.

### Enable Quantity Selection

Turn on to enable the customer to change the quantity of a product on checkout. To use this feature, the metadata option sb\_quantity\_enabled: true must be on the Stripe Product. Learn more about this feature [here](/how-to/enable-quantity-management).

### Show total price in checkout

Turn on to show the total price to the customer when quantity is modified. Currently this only works with flat subscription models. Support for Volume and Graduated pricing models coming soon!

### Enable Redirect URL

Turn on to enter a redirect URL when customers have successfully checkout out. This can be a full or or relative URL.

### Limit One Subscription per Email

Turn on to limit one subscription per email. If a customer already has a subscription, an error will be shown. Stripe is queried to see if a subscription already exists for a customer with the entered email.

### Set Customer Name from Card

Turn on to have the Customer object in Stripe to be populated with the value from the Name on Card field.

### Dynamically Pass User's Identity

Turn on this option to dynamically pass in a customer's email or Stripe Customer ID. If a value is passed in, the checkout form will not ask the customer for an email.&#x20;

If using this option, you must pass in a value to the embed snippet for either 'email' or stripe 'customer\_id'. You will find it in the Billflow window settings of the embed snippet.&#x20;

### Enable Automatic Tax

Automatic Tax Calculation. Contact us for beta access to this feature.

### Enable VAT ID Field

Collect a customer's VAT ID, it will be added to the Stripe Customer Object.

### Select a VAT ID type

Select a VAT ID type. Eg: if you are in the EU, select the EU VAT option.

## Language Settings

All Billflow billing pages have the ability to automatically detect the customer's browser language preference and translate the billing page accordingly. If the language is not supported by our page, a default language will be displayed. The default language is English US.

### Automatically Detect User's Browser Settings

Turn on to automatically detect the customer's browser settings and translate the page. If not enabled, select your default language. Not seeing a language you need there? Contact us on the chat to request a translation.

### Add a Custom Resource

Turn this option on to pass in your own translations. This can be used to host your own language files, but can also be used to change the text of specific sections to your desired text. To learn more about this option, read along [here](/how-to/internationalization/support-multiple-languages#resources). &#x20;

## Advanced Settings

### Enable Handle Response&#x20;

Turn on to enable the handleResponse function. The function is used to handle events with custom code when events happen on the billing page like button clicks and actions performed. To learn more about events available and sample code snippets, read along [here](/developers/handling-embed-events).&#x20;

### Debug Mode

Turn on to enable debug mode for extra console logging.

## Embed

Embedding the Checkout Form is a one-step process. Just copy and paste the provided HTML snippet.&#x20;

If you have a frontend framework, check out the [samples](/developers/languages-and-frameworks) of embedding with those.

## Popular How-to's

{% content-ref url="/pages/-MGp022oJ-7-OcCyEsXR" %}
[Checkout Form Style Templates](/how-to/change-style/checkout-form-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MGj2f1k66M4G\_H0Blws" %}
[Use Coupons](/how-to/use-coupons)
{% endcontent-ref %}

{% content-ref url="/pages/-MIRiVvAUx5ULOuNm01Q" %}
[Enable Quantity Management](/how-to/enable-quantity-management)
{% endcontent-ref %}

## Developers

The Checkout Form has many more powerful features that can be unlocked with some simple coding. Check out the developer docs to learn more.

{% content-ref url="/pages/-MGTmTB\_dnRVUsObnb\_g" %}
[Embed Configurations](/developers/embed-configurations)
{% endcontent-ref %}


# Customer Portal

Customer Portal Overview, Features, & How-To's

![](/files/-MQmbxGOBfSgBZfnTb73)

## Overview

The Billflow Customer Portal gives your customers a page to self-manage their subscriptions. It works with any subscriptions created in Stripe whether that be from Billflow, a custom Stripe integration, or another 3rd party app.&#x20;

You can configure the actions a user can perform in the portal, as well as enable options to increase up-sells and reduce churn.

The Customer Portal has a simple HTML/Javascript embed so it can be embedded onto any website that will accept this common embed method. It authorizes users with a security hash generated with the logged-in user's email or Stripe Customer ID. This method of authorization allows Billflow to work with any authentication provider. Make sure to check out plugins to make integration easier.

## Customer Portal Settings

### How to Identify Customers

You must choose how you will identify customers. You have an option to pass in a customer's **email** address or their **Stripe Customer ID** in order for Billflow to look up their information in Stripe.&#x20;

Identifying with email is simpler as it requires less data to store. Identifying with Stripe Customer ID is more robust because you do not need to handle email changes and is also needed when doing a tenant based architecture where multiple account are under the same group.

### Enable Change Plan

Turn on to allow customers to change their plan. This will allow them to upgrade or downgrade between available tiers and change their billing interval. You must have a Service configured to use this feature, if you have not created a Service, you can read how to [here](/how-to/setup-pricing).

### Allow Resubscribe

Turn on to allow customers who have cancelled their subscription to resubscribe. Stripe does not allow a subscription in 'canceled' state to become 'active' again so this creates a new subscription based on the same Product.

### Allow Plan Change for Canceled Subscriptions

Turn on to allow customers with a canceled subscription to change their plan and resubscribe. Both Change Plan and Resubscribe need to be enabled to allow for this feature.

### Enable Coupon

Turn on to allow customers to enter a coupon from the customer portal. This feature is great for running promotions and retention campaigns. The coupon codes are configured in the Stripe Dashboard, to learn how read [here](/how-to/use-coupons).

### Enable Security Hash

Turn on to enable security on your page in test mode. This option is required in live mode. In order for the customer portal to securely display customer billing information, a hash must be passed to the billing page options. This hash must be generated on the server with the logged in user's email or Stripe customer ID, whichever you are using to identify users. This step is covered in more detail in the [Secure Setup](/billing-pages/customer-portal#authentication-secure-setup).

### Enable coupon for resubscribe

Turn on to allow customers to enter a coupon code when they resubscribe to a cancelled subscription. This is a great way to gain back previously canceled customers.

### Show pricing for logged in users

This will show the plan picker for logged in users who have a subscription. In most scenarios, if using this option you should create a Plan Picker instead. Useful if you only need to show plans for existing customers.

### Use Dropdown menu for subscription actions

Turn on to have the subscription actions be in a dropdown instead of buttons.&#x20;

### Enable update card

Turn on to allow customers to update their payment information. This is a great way to reduce churn as a big amount of churn simply comes from expired or canceled credit cards. For more information on handling dunning, read [here](/how-to/cancellations-payment-failures/configure-dunning-emails).

### Show all customer invoices

Turn on to show all customer invoices including one-time invoices. By default, the invoices section will only show invoices related to the subscription the customer is viewing. If you do enterprise deals or one-off invoicing for services, enable this so customers can view all their invoices.

### Enable quantity management

Turn on to allow customers to change the quantity of their subscription. This feature requires an additional metadata tag and unit label on the Stripe Product. Read [here](/how-to/enable-quantity-management) to learn about using this feature.

### Enable cancellation

Turn on to allow customer to self-service canceling their subscription. Self-service reduces customer support load, but disabling can create more feedback for customer success teams.

### Cancellation Reason

Turn on to ask customers why they are leaving. This will prompt the customer to give a reason for their cancelation so you can improve your service. The reason will be added as metadata on the cancelled Stripe subscription.

### Cancel Immediately

Turn on for the subscription to cancel immediately. By default, the subscription will cancel at the end of the billing period.

### Confirmation message when user requests cancellation

Customize the message the user sees when they confirm their cancellation.&#x20;

## Language Settings

All Billflow billing pages have the ability to automatically detect the customer's browser language preference and translate the billing page accordingly. If the language is not supported by our page, a default language will be displayed. The default language is English US.

### Automatically Detect User's Browser Settings

Turn on to automatically detect the customer's browser settings and translate the page. If not enabled, select your default language. Not seeing a language you need there? Contact us on the chat to request a translation.

### Add a Custom Resource

Turn this option on to pass in your own translations. This can be used to host your own language files, but can also be used to change the text of specific sections to your desired text. To learn more about this option, read along [here](/how-to/internationalization/support-multiple-languages#resources). &#x20;

## Advanced Settings

### Enable Handle Response&#x20;

Turn on to enable the handleResponse function. The function is used to handle events with custom code when events happen on the billing page like button clicks and actions performed. To learn more about events available and sample code snippets, read along [here](/developers/handling-embed-events).&#x20;

### Debug Mode

Turn on to enable debug mode for extra console logging.

## Authentication Settings

There are two ways to get users authenticated with the customer portal to securely view their billing information.&#x20;

### Integrate with existing authentication

The first method is to integrate with your existing authentication system if you have one for your app or website. This will be the preferred choice for SaaS applications. For more details on that, jump to the [Secure Setup](/billing-pages/customer-portal#authentication-secure-setup) section.&#x20;

### Billflow email auth

The second method is to use Billflow's Email Authentication option. This option allows you to add the customer portal to any website and simplifies the installation. If a customer goes to the page on your site with the customer portal, they will first see an option to enter in the email to get an access link. Submitting will send them an email which will take them back to the same page with a token, allowing them to view their billing information.&#x20;

Set your company name that the email sender should be shown as. Set your redirect URL to the URL where you have embedded the customer portal. A token will automatically be added to that URL when emails are sent.

## Embed

Embedding the Customer Portal is a two-step process. For the client side installation just copy and paste the provided HTML snippet. The next step is secure setup.

If you have a frontend framework, check out the [samples](/developers/languages-and-frameworks) of embedding with those.

## Authentication Secure Setup

The customer portal must be behind some kind of user authentication in order to safely show customers their billing information. Billflow authenticates users with an HMAC hash generated for the logged-in user, this allow is to work with any authentication system. If you are using a No-code platform, make sure to check out our plugins as they handle this step for you. If you are integrating into a custom application, continue on.

Your code to generate an HMAC for your app must be placed in the back-end of your application. Grab the snippet from the dashboard to add to your server. You may generate the HMAC with the user's **email** OR the user's **Stripe Customer ID** (customer\_id).

The HMAC generated will be passed to the client-side snippet to a property called 'hash'.

{% hint style="info" %}
Don't see your server-side language listed? Let us know and we'll get a code snippet for you!
{% endhint %}

{% tabs %}
{% tab title="Node.js" %}

```javascript
const crypto = require("crypto");
const email_hash = crypto.createHmac(
    "sha256",
    "YOUR_SECRET_KEY" // SECRET KEY (KEEP SAFE!)
).update(req.user.email).digest("hex") // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Rails (Ruby)" %}

```ruby
email_hash = OpenSSL::HMAC.hexdigest(
    'sha256', # HASH FUNCTION
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    current_user.email # REPLACE WITH USER'S EMAIL ADDRESS
) # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Django (Python)" %}

```python
import hmac
import hashlib

email_hash = hmac.new(
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    request.user.email, # REPLACE WITH USER'S EMAIL ADDRESS
    digestmod=hashlib.sha256 # HASH FUNCTION
).hexdigest() # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="PHP" %}

```php
$email_hash = hash_hmac(
    'sha256', // HASH FUNCTION
    $user->email, // REPLACE WITH USER'S EMAIL ADDRESS
    'YOUR_SECRET_KEY' // SECRET KEY (KEEP SAFE!)
); // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Other" %}
Generate an HMAC with SHA256 whenever a user logs into your app. Most web frameworks will have a method or library to help you do this. You'll need your app’s secret key and the email or user\_id of the currently logged-in user.

Secret Key\
[**Get Your Secret Key**](https://dashboard.servicebot.io/billing-embed)
{% endtab %}
{% endtabs %}

Seeing 403s? You can verify your HMAC is being generated properly by creating one [here](https://www.freeformatter.com/hmac-generator.html). Use "SHA256", pass in the customer's email or customer ID, and use your Billflow secret key as the secret. Compare that with what you're generating server-side and what's being passed to the client-side.

{% hint style="warning" %}
**Keep your secret key safe!** Never commit it directly a public repository, client-side code, or anywhere a third party can find it.
{% endhint %}

{% hint style="info" %}
Don't forget to check out our [integration samples](/developers/languages-and-frameworks)!
{% endhint %}

## Popular How-to's

{% content-ref url="/pages/-MGp-woNQpzKtTivzid\_" %}
[Customer Portal Style Templates](/how-to/change-style/customer-portal-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MIRiVvAUx5ULOuNm01Q" %}
[Enable Quantity Management](/how-to/enable-quantity-management)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTQwVN9cxVxBD8FgtP" %}
[Connect to SaaS](/how-to/connect-to-saas)
{% endcontent-ref %}

## Developers

The pricing page has many more powerful features that can be unlocked with some simple coding. Check out the developer docs to learn more.

{% content-ref url="/pages/-MGTmTB\_dnRVUsObnb\_g" %}
[Embed Configurations](/developers/embed-configurations)
{% endcontent-ref %}


# Pricing Page

Pricing Page Overview, Features, & How-To's

![](/files/-MQmeslP8AePLkI1an73)

## Overview

The Billflow Pricing Page allows you to easily show your product pricing on your marketing site and let users checkout. Because it's connected directly to your Stripe account, you never have to worry about updating your website when you change your pricing.

You can chose to redirect users after they select a plan to your own signup process, or you can let users automatically go to the Billflow Checkout Form to enter payment information and then show them a custom message or redirect them to another step.&#x20;

The Pricing Page has a simple HTML/Javascript embed so it can be embedded onto any website that will accept this common embed method.

#### Steps to create a Pricing Page

## Select a Service

A Service is a collection of Stripe Products & Prices that make up the tiers & intervals of a service offering. If you have not created a service already, you will have the option to create a 'demo' service. To learn how to create your own service and specific pricing model, [real along here](/how-to/setup-pricing).&#x20;

Select the service you wish to create a Pricing Page for.

{% hint style="info" %}
Not seeing a service listed that you created in Stripe? Make sure you have that service in the same mode (Test or Live) that your billing page is in.&#x20;
{% endhint %}

## Pricing Page Settings

Following are the options available on the Pricing Page

### Hide Tiers

Want to hide a certain tier that's only available to a certain group or an a certain time? Use hide tiers to select from your available tiers and leads will not see it as an option.

### Disable Tiers

Want to disable certain tiers to run a promotion of things to come? Use disable tiers to select from your available tiers and leads will see that tier greyed and unavailable now.

### Default Interval

Select a billing interval to be the default.&#x20;

### Show monthly rate on Annual plans

Turn this option on to show how much the annual plans cost as a monthly rate. Eg: A $120/yr plan would show $10/mo billed annual

### Show discount on Annual plans

Turn this option on to show a discounted flag on the annual plans.

### Show all interval plan on the same page

This option will show all plans in the configured service together as opposed to showing only plans in a given interval with an interval toggle.

### Hide the interval selector

This option will hide the interval toggle and show only the plans in the default interval. This can be used if you want to show only monthly plans on one page, and only annual on another.

### Interval selector alignment

Choose the alignment of the interval toggle, left, right, or center.

### Default Interval

Select a billing interval to be the default.&#x20;

### Custom Interval

Only use this option if you want to change the default interval and you have a custom interval like "Every 3 months" or "Every 6 weeks". The value will just be the number in your interval.

### Pre-applied Coupon

Fill this option in with a Stripe Coupon ID or Promo Code to have a coupon automatically applied to any tier chosen. Useful feature for running a promotion on a specific URL.&#x20;

### Which checkout do you want to use?

Choose to show the default Billflow Checkout Form after Plan selection, or redirect to another URL. Redirect can go to an app for registration or to a different page for other checkout process.

## Checkout Form Settings

When a user selects a plan on the Pricing Page, it will automatically go to the correct Checkout Form for that tier. To learn more about the options available on it or about embedding a separate Checkout Form, check out the [Checkout Form](/billing-pages/checkout-form#checkout-form-settings). &#x20;

## Language Settings

All Billflow billing pages have the ability to automatically detect the customer's browser language preference and translate the billing page accordingly. If the language is not supported by our page, a default language will be displayed. The default language is English US.

### Automatically Detect User's Browser Settings

Turn on to automatically detect the customer's browser settings and translate the page. If not enabled, select your default language. Not seeing a language you need there? Contact us on the chat to request a translation.

### Add a Custom Resource

Turn this option on to pass in your own translations. This can be used to host your own language files, but can also be used to change the text of specific sections to your desired text. To learn more about this option, read along [here](/how-to/internationalization/support-multiple-languages#resources). &#x20;

## Advanced Settings

### Enable Handle Response&#x20;

Turn on to enable the handleResponse function. The function is used to handle events with custom code when events happen on the billing page like button clicks and actions performed. To learn more about events available and sample code snippets, read along [here](/developers/handling-embed-events).&#x20;

### Debug Mode

Turn on to enable debug mode for extra console logging.

## Embed

Embedding the Pricing Page is a one-step process. Just copy and paste the provided HTML snippet.&#x20;

If you have a frontend framework, check out the [samples](/developers/languages-and-frameworks) of embedding with those.

## Change Tier and Plan Order

You can modify the order that tiers appear from their default ordering by price. Metadata tags are used in Stripe to do this, add these to your Stripe Product.

| Metadata Key             | Description                                                                                                              | Example Values |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------ | -------------- |
| sb\_pricing\_tier\_order | Add this metadata property to a Stripe Product. The lowest value tier appears left-most on your Pricing page.            | 1              |
| sb\_pricing\_plan\_order | Add this metadata property to a Stripe Plan. The lowest value plan appears higher on a tier with multiple pricing plans. | 5              |

## Popular How-to's

{% content-ref url="/pages/-MGp0-9miuJk6ZYPbdIy" %}
[Pricing Page Style Templates](/how-to/change-style/pricing-page-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTQkw2hhQNZqLuVJ70" %}
[Update Pricing](/how-to/update-pricing)
{% endcontent-ref %}

## Developers

The pricing page has many more powerful features that can be unlocked with some simple coding. Check out the developer docs to learn more.

{% content-ref url="/pages/-MGTmTB\_dnRVUsObnb\_g" %}
[Embed Configurations](/developers/embed-configurations)
{% endcontent-ref %}


# Invoice Portal

Invoice Portal Overview, Features, & How-To's

![](/files/-MQmfYUxylYPWCejCh4V)

## Overview

The Billflow Invoice Portal gives your customers a page to view, pay, and download their invoices. It works with any invoices created in Stripe whether that be from Billflow, a custom Stripe integration, or another 3rd party app.&#x20;

You can configure the actions a user can perform in the portal, as well as enable options to increase up-sells and reduce churn.

The Invoice Portal has a simple HTML/Javascript embed so it can be embedded onto any website that will accept this common embed method. It authorizes users with a security hash generated with the logged-in user's email or Stripe Customer ID. This method of authorization allows Billflow to work with any authentication provider. Make sure to check out plugins to make integration easier.

## Invoice Portal Settings

### How to Identify Customers

You must choose how you will identify customers. You have an option to pass in a customer's **email** address or their **Stripe Customer ID** in order for Billflow to look up their information in Stripe.&#x20;

Identifying with email is simpler as it requires less data to store. Identifying with Stripe Customer ID is more robust because you do not need to handle email changes and is also needed when doing a tenant based architecture where multiple account are under the same group.

### Enable Security Hash

Turn on to enable security on your page in test mode. This option is required in live mode. In order for the customer portal to securely display customer billing information, a hash must be passed to the billing page options. This hash must be generated on the server with the logged in user's email or Stripe customer ID, whichever you are using to identify users. This step is covered in more detail in the [Secure Setup](/billing-pages/invoice-portal#authentication-secure-setup).

### Show all customer invoices

Turn on to show all customer invoices including one-time invoices. By default, the invoices section will only show invoices related to the subscription the customer is viewing. If you do enterprise deals or one-off invoicing for services, enable this so customers can view all their invoices.

## Language Settings

All Billflow billing pages have the ability to automatically detect the customer's browser language preference and translate the billing page accordingly. If the language is not supported by our page, a default language will be displayed. The default language is English US.

### Automatically Detect User's Browser Settings

Turn on to automatically detect the customer's browser settings and translate the page. If not enabled, select your default language. Not seeing a language you need there? Contact us on the chat to request a translation.

### Add a Custom Resource

Turn this option on to pass in your own translations. This can be used to host your own language files, but can also be used to change the text of specific sections to your desired text. To learn more about this option, read along [here](/how-to/internationalization/support-multiple-languages#resources). &#x20;

## Advanced Settings

### Enable Handle Response&#x20;

Turn on to enable the handleResponse function. The function is used to handle events with custom code when events happen on the billing page like button clicks and actions performed. To learn more about events available and sample code snippets, read along [here](/developers/handling-embed-events).&#x20;

### Debug Mode

Turn on to enable debug mode for extra console logging.

## Embed

Embedding the Invoice Portal is a two-step process. For the client side installation just copy and paste the provided HTML snippet. The next step is secure setup.

If you have a frontend framework, check out the [samples](/developers/languages-and-frameworks) of embedding with those.

## Authentication Secure Setup

The customer portal must be behind some kind of user authentication in order to safely show customers their billing information. Billflow authenticates users with an HMAC hash generated for the logged-in user, this allow is to work with any authentication system. If you are using a No-code platform, make sure to check out our plugins as they handle this step for you. If you are integrating into a custom application, continue on.

Your code to generate an HMAC for your app must be placed in the back-end of your application. Grab the snippet from the dashboard to add to your server. You may generate the HMAC with the user's **email** OR the user's **Stripe Customer ID** (customer\_id).

The HMAC generated will be passed to the client-side snippet to a property called 'hash'.

{% hint style="info" %}
Don't see your server-side language listed? Let us know and we'll get a code snippet for you!
{% endhint %}

{% tabs %}
{% tab title="Node.js" %}

```javascript
const crypto = require("crypto");
const email_hash = crypto.createHmac(
    "sha256",
    "YOUR_SECRET_KEY" // SECRET KEY (KEEP SAFE!)
).update(req.user.email).digest("hex") // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Rails (Ruby)" %}

```ruby
email_hash = OpenSSL::HMAC.hexdigest(
    'sha256', # HASH FUNCTION
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    current_user.email # REPLACE WITH USER'S EMAIL ADDRESS
) # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Django (Python)" %}

```python
import hmac
import hashlib

email_hash = hmac.new(
    'YOUR_SECRET_KEY', # SECRET KEY (KEEP SAFE!)
    request.user.email, # REPLACE WITH USER'S EMAIL ADDRESS
    digestmod=hashlib.sha256 # HASH FUNCTION
).hexdigest() # PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="PHP" %}

```php
$email_hash = hash_hmac(
    'sha256', // HASH FUNCTION
    $user->email, // REPLACE WITH USER'S EMAIL ADDRESS
    'YOUR_SECRET_KEY' // SECRET KEY (KEEP SAFE!)
); // PASS THIS TO FRONT-END
```

{% endtab %}

{% tab title="Other" %}
Generate an HMAC with SHA256 whenever a user logs into your app. Most web frameworks will have a method or library to help you do this. You'll need your app’s secret key and the email or user\_id of the currently logged-in user.

Secret Key\
[**Get Your Secret Key**](https://dashboard.servicebot.io/billing-embed)
{% endtab %}
{% endtabs %}

Seeing 403s? You can verify your HMAC is being generated properly by creating one [here](https://www.freeformatter.com/hmac-generator.html). Use "SHA256", pass in the customer's email or customer ID, and use your Billflow secret key as the secret. Compare that with what you're generating server-side and what's being passed to the client-side.

{% hint style="warning" %}
**Keep your secret key safe!** Never commit it directly a public repository, client-side code, or anywhere a third party can find it.
{% endhint %}

{% hint style="info" %}
Don't forget to check out our [integration samples](/developers/languages-and-frameworks)!
{% endhint %}

## Popular How-to's

{% content-ref url="/pages/-MGp0NMvKEQhmdZnAkHD" %}
[Enterprise Sales Flow](/how-to/enterprise-sales-flow)
{% endcontent-ref %}

## Developers

The invoice portal has many more powerful features that can be unlocked with some simple coding. Check out the developer docs to learn more.

{% content-ref url="/pages/-MGTmTB\_dnRVUsObnb\_g" %}
[Embed Configurations](/developers/embed-configurations)
{% endcontent-ref %}


# Setup Pricing

Billflow can help you recreate a variety of pricing models, everything ranging from a basic flat subscription to a more complex per usage model and anything in between. Below are the most common pricing models:&#x20;

1. **Flat-rate Subscription** -- Flat rate pricing is a very simple strategy with a single tier charging a flat rate subscription to unlock all features within a product.&#x20;
2. **Unit** --  Most B2B SaaS companies are using some form of usage-based pricing. Being able to bill a customer based on how much value they are getting out of a product is critical to running a business.&#x20;
3. **Metered** -- Often times it is valuable to gain an insight in to how the product is being used. There are several ways set up in Stripe to monitor usage and bill off that.&#x20;
4. **Setup Fee** -- Most digital agencies use a Setup fee.&#x20;
5. **Complex** -- When one model does not exactly fit the needs of your company or vision, utilizing a blend of features from these models is most effective.&#x20;

If you would like to learn more about the different pricing models, and which may work best for you [read along here](https://www.servicebot.io/saas-billing-pricing-models).&#x20;

Regardless of the complexity of your pricing model, two things always stay constant: "Product" creation in Stripe and metadata tagging in Stripe.

Once you have your pricing plan in mind, you are ready to recreate it using Stripe.&#x20;

Product creation in stripe is a two step process. First, you enter the  details corresponding with a tier/ metric of your choice and then save your product.&#x20;

![](/files/-MJ4CQEHCWzhdWnyjtSK)

For Billflow to know which product belongs to your service you must utilize metadata tags. Every product that corresponds to your service's particular plan must be tagged with the same ''sb\_service" tag. In addition, each of these products will have a unique "sb\_tier" that corresponds to the particular price of that tier. The "sb\_service" tag encapsulates all of the products that you created for a particular plan. This is what "glues" the products together. The "sb\_tier" tag is what differentiates one product from the next in your plan. As such, it is important that your "sb\_service" tag do not change within the plan. And your "sb\_tier" tags change with the tier that you create.&#x20;

![](/files/-MJ4jswEOlJtDbjxDroR)

Going back to Billflow, refreshing the "Pricing Plan" page should allow for you to see your newly created model. If you have multiple services created in Stripe, select the service that you have just created. As an example the end result of a three tiered pricing model is shown below.&#x20;

![](/files/-MQmgGvcxrm-x_B2kvZ3)


# Flat-rate Subscriptions

How to create a Flat-rate pricing model

{% embed url="<https://youtu.be/DtXjrQyN53Y>" %}

If your pricing model resembles something that is independent of a metric and is charged on a recurring basis, then this Flate-rate Subscription guide is for you. You can also consider using flat-rate if your product is at a very early stage, and the SaaS company just wants to start charging customers.&#x20;

Once you have established how many different plans you are to have, you need to create a product for each of them. For example, let's take a model that will have two pricing plans (Basic and Pro). In this case we will create a product for each of these.  Creating a product in "Stripe" is as simple as clicking "+ Product"

![](/files/-MJ3Owp9tWG8u5RH_J-s)

If you would like to use a yearly pricing plan instead of monthly or in addition to a monthly plan, there is only a small change in the process to be made. When creating your product you would create an additional price and set the recurring rate to yearly.

![](/files/-MJ8L2EpCGDwrm98UEBR)

Now that we are done creating the products, for Billflow to recognize these products as a single service we need to tag it with an "sb\_service" tag. This tag should be the same for all products(pricing plans) that are in the model. Next we tag each with a unique "sb\_tier" that corresponds to the plan. That means we have 2 unique "sb\_tier" tags for our example.&#x20;

![](/files/-MJ3W5YQ9qZ4sdld0ia3)

Finally, we go back to Billflow and refresh the "Pricing Plan" page. We should see our pricing plan pop up.&#x20;

![](/files/-MJ3XaZLr9aTVqiLYXeS)


# Free Trial

How to add a free trial

Free trials are configured on the Stripe Price. You can add a number of trial days to any plan, configured under Additional Options. Stripe is deprecating this so in the future it will be configured on the Billflow dashboard. For the time being it is safe to configure this on the Price.

![](/files/-MRLAtdJ33JrumStCVHZ)


# Unit-based

How to create unit based or per-seat pricing

Most B2B SaaS companies should be using some form of usage-based pricing. Being able to bill a customer based on how much value they are getting out of a product is critical to running a business.&#x20;

There are two different unit-based pricing models that you are able to reproduce in Billflow. The first is per User per month and the other is a graduated pricing model given the number of units of something purchased.&#x20;

Similar to the Flatrate subscription model, you must create a product for every tier of pricing that you will have. Next, we will utilize a unique  unit label found within the product creation window to assist in creating the per User pricing.&#x20;

![](/files/-MJ3sg7DmKGvrRqdWcqg)

As a note: if you would like to create yearly pricing based on user per month, this would be the place to do so when creating the product. Scroll down to pricing and create the pricing with the recurring rate set to yearly.&#x20;

We repeat this for every pricing tier that we have. We also need to make sure that we are still tagging the products with the "sb\_service" and "sb\_tier" tags. The "sb\_service" tags stay consistent with every product you are creating and the "sb\_tier" tag changes with the tier that you are creating. Once you are done tagging, go back to the pricing page in Billflow and refresh the page. Your pricing model should now pop up. Note: The below image is an example of when solely selecting monthly pricing.&#x20;

![](/files/-MJ3ssjdx2lxJ9tlfQ_u)

The second type of Unit based pricing is a graduated pricing model. Although fundamentally different than the Flat-rate Subscriptions, This Unit based pricing follows a similar pattern for the creation of the previous pricing model. The main difference is that instead of using the "Standard Pricing" option we will be using the "Graduated Pricing". The neat thing about having the graduated pricing model is that you are able to have a custom "unit label''. Once created, it will be recognized as whatever you wanted it to be instead of the generic per "unit" given in Stripe.&#x20;

![](/files/-MJ3teSfMR6Qtk7VjE-N)

After filling out the above pricing table, we follow the same step in tagging our product with the "sb\_service" and ''sb\_tier" tags.&#x20;

Heading back to Billflow, we refresh the page and should see our "Pricing Page" pop up. We will see the first pricing tier and underneath there will a link that will then show the rest of the gradations.&#x20;

![](/files/-MJ3uFvWTYunGm5pMju5)

For more information on allowing users to set the quantity themselves, check out the [Quantity Management](/how-to/enable-quantity-management) feature.&#x20;

To learn how to update the quantity via the API, continue [here](/how-to/record-usage#record-units-in-stripe).&#x20;


# Meter-based

Once you have established how many different plans you are to have, you need to create a product for each of them. For example, lets take a model that will have three pricing plans (Basic and Pro). In this case we will create a product for each of these.  Creating a product in "Stripe" is as simple as clicking "+ Add Product"

The trick for metered usage is ticking the box at the bottom of the "Product" creation page. This will make it so that now on top of the basic flat subscription for a tier there is a metered usage message added. As a note: if you would like to create yearly pricing based on user per month, this would be the place to do so when creating the product. Scroll down to pricing and create the pricing with the recurring rate set to yearly.&#x20;

![](/files/-MJ3d1aK4jGd-Mp6tswy)

Now that we are done creating the products, for Billflow to recognize these products as a single service we need to tag it with an "sb\_service" tag. This tag should be the same for all products(pricing plans) that are in the model. Next we tag each with a unique "sb\_tier" that corresponds to the plan. That means we have 3 unique "sb\_tier" tags for our example.&#x20;

Finally, we go back to Billflow and refresh the "Pricing Plan" page. We should see our pricing plan pop up. Note: only the basic tier was produced for the example. The tagging and production of the Pro tier is exactly the same and will yield a similar result.&#x20;

![](/files/-MJ3q7Z_4Ru01C5Yz2G0)

To learn how to update metered usage via the API, continue [here](/how-to/record-usage#record-metered-usage-in-stripe).&#x20;


# Setup Fees

Setup Fees are common with digital agencies. If your company has a similar ethos, this may be the model for you. To create this model it is quite easy as it is a simple step from the creation of a flatrate subscription model. Not to mention, you can add a Setup fee to any of your pricing models utilizing the same process. Once you have established how many different plans you are to have, you need to create a product for each of them. In addition to creating a product for each of your tiers, you will need to create a product for each of "Setup Fees" corresponding to each plan.&#x20;

![](/files/-MJDklrHhw5VWefwQo7s)

Now that we are done creating the products, for Billflow to recognize these products as a single service we need to tag it with an "sb\_service" tag. This tag should be the same for all products(pricing plans) that are in the model. Next we tag each with a unique "sb\_tier" tag that corresponds to each plan. Also important, is that you want to match the metadata tags on your "Setup Fee" product(s) to the corresponding original products. This way Billflow will know to include your "Setup Fee" in each of the corresponding tiers. &#x20;

We go back to Billflow and refresh the page. Now, we should see our Pricing model. Building up a Setup fee for our Flatrate example, we can see the following in Billflow.&#x20;

![](/files/-MQmhMGUVFD3Qq61QZjV)


# One-Time Payment

How to create a one-time payment

If you want to collect a one-time payment for a life-time subscription, a one-off service, or physical goods, you can do so by creating a one-time product in Stripe. Creating a product in "Stripe" is as simple as clicking "+ Product"

![](/files/-MJ3Owp9tWG8u5RH_J-s)

Next you can set the product to One-time so the customer is only billed once. Billflow will take care of displaying that for you.

![](/files/-MJDklrHhw5VWefwQo7s)

Now that we are done creating the products, for Billflow to recognize these products as a single service we need to tag it with an "sb\_service" tag. This tag should be the same for all products(pricing plans) that are in the model. Next we tag each with a unique "sb\_tier" that corresponds to the plan. That means we have 2 unique "sb\_tier" tags for our example.&#x20;

![](/files/-MJ3W5YQ9qZ4sdld0ia3)

Finally, we go back to Billflow and refresh the "Pricing Plan" page. We should see our pricing plan pop up.&#x20;

![](/files/-MYM0RnDxEkgxGgfwaRk)


# Payment Plans (Subscription Schedules)

How to create a payment plan

There are several uses for the Payment Plan or split payments Pricing model. The first is to break a large one-time payment into several monthly payment to increase sales of a given product. The second is to create an automatically cancelling subscription that behaves like a paid trial of a service. The setup for both of those scenarios is the same and we start by creating a Product in Stripe.

![](/files/-MJ3Owp9tWG8u5RH_J-s)

You will configure a Recurring product so that the customer is charged on the given billing interval. You can set the Billing period to any interval you need, and monthly is most common.

![](/files/-MJ8L2EpCGDwrm98UEBR)

Now that we are done creating the products, for Billflow to recognize these products as a single service we need to tag it with an "sb\_service" tag. This tag should be the same for all products(pricing plans) that are in the model. Next we tag each with a unique "sb\_tier" that corresponds to the plan. That means we have 2 unique "sb\_tier" tags for our example. \
Specifically for Payment Plans, we need to add a third metadata value and that is "sb\_plan\_iterations". Set this to the number of times the customer should be charged. For example, if you want the customer to pay $600 in 6 monthly $100 payments, the value of "sb\_plan\_iterations" would be 6. After 6 months, the subscription will automatically cancel.

![](/files/-MYM4bEYCjCP22BTsj4Y)

Finally, we go back to Billflow and refresh the "Pricing Plan" page. We should see our pricing plan pop up.&#x20;

![](/files/-MYM4tvDnQrShv8L4CpE)


# Complex Pricing

## Setup a complex pricing model

Now that we've learned how to reproduce some of the more basic pricing models we can add bits and pieces of other models to better fit the needs of your company. These basic models  do not have to be mutually exclusive from one another. Here we will take an example where we bring everything together into one pricing model. The example below illustrates two tiers with flatrate pricing in addition to pricing per unit.&#x20;

We start off by creating our products normally. Since we will have two tiers we will need to create two products. The first price will be as usual, the standard recurring price. The second price will be of the graduated pricing model as used previously to demonstrate per Unit pricing.&#x20;

![](/files/-MJ4C7qP31Soto_VRDxX)

Then as normal we must tag both products with metadata, so that the  pricing model will populate in Billflow's Pricing Page. As usual, "sb\_service" is the same for both of our products and the "sb\_tier" tags are different and correspond to each tier. Once more, we refresh the Pricing Page and should see our product pop up.&#x20;

![](/files/-MJ4BvJtJn1Dryy5NT9T)


# Add-ons

Configure add-ons to expand your revenue

With Billflow you can sell one-time and subscription add-ons with your plans. These can be shown on the Checkout Form and/or the Customer Portal. Leverage these to start expanding your revenue!

## How it works

### Checkout Form

If add-ons are configured, they will appear below the standard configured products in the checkout form. Your customer is able to select them while checking out and add one-time payments or subscriptions. The total amount will be recalculated and taxes included if configured. [Live example](https://codepen.io/kslung/pen/BaRJwYx)

![Add-ons on checkout](/files/-MfbtjucKDHMIheWT8s9)

### Customer Portal

The customer portal will allow customers to add configured one-times or subscriptions, and manage existing ones.&#x20;

One-time add-ons can be added as many times as the user wishes. This feature can be leveraged to create a credit-based pricing model where a customer adds credits to your platform with a one-time payment.&#x20;

Subscription add-ons can be turned on or off so you can sell an additional feature or service.&#x20;

[Live example](https://codepen.io/kslung/pen/gOWoJOL)

![Add-ons on Customer Portal](/files/-MfbuqsT-we27OLMXHtB)

## Setup Stripe Product

As with standard pricing models, metadata needs to be added to your Stripe products. A new product should be created for each add-on. If you want a single add-on to be available on every tier in your service, then only configure the sb\_service key, and leave out the sb\_tier key.&#x20;

Add-ons can also use the [Quantity Management](/how-to/enable-quantity-management) feature. Set a unit\_label for the product for Billflow to recognize it as a quantity enabled product.&#x20;

Below is the relevant metadata.

| Key         | Value           | Notes                                   |
| ----------- | --------------- | --------------------------------------- |
| sb\_addon   | true            | Enables a product as an add-on          |
| sb\_service | *your\_service* | Configured service to add the add-on to |
| sb\_tier    | *your\_tier*    | Limits the add-on to a single tier      |


# Connect to SaaS

Learn about integrating Billflow with your SaaS

We want to get users into your product as fast as possible so they see the value of your service and turn into happy paying customers. The Billflow on-boarding flow is meant to reduce friction for your users so you increase your conversion rate. Whether you offer a free trial, ask for CC up front, or run a freemium model, Billflow has you covered.

## Overview

SaaS billing has a strong connection to user registration and the on-boarding flow of your application. From the time the user visits your website, to when they're paying you every month for your product, you need to understand their journey.&#x20;

Are you providing freemium accounts? Free trials? or simply charging your customers upon registration? Depending on your pricing strategy you will have a different billing flow.

![](/files/-MQmt81mIEn4tWbAOYF-)

The first step of setting up your SaaS billing is to understand how you are planning on charging your customers and your pricing strategy. Check out our [quiz](https://demo.billflow.io/saas-billing-flows) to get the billing flow needed for your setup.&#x20;

{% embed url="<https://demo.billflow.io/saas-billing-flows>" %}

## Acquisition Strategy

If you are running a SaaS product, most likely you have a user registration process. This is the process you use to onboard your users and give them access to your application. In many cases you'll need to create user's billing profiles in Stripe during on-boarding. Depending on your on-boarding strategy, your user billing registration flow might look different. You must know which of the following strategies you fall under:

#### Freemium Accounts

If you have a free plan, then you are on-boarding your users to your application before they pay you. With the freemium models you don't have to create any billing profiles for your users until they are ready to pay you. Just give your users access to your SaaS, and redirect them to a page with the Billflow Plan Picker and Billflow will handle plan selection, checkout, and creation of Stripe Customer/Subscription for you.

#### Free Trial Accounts

If you are starting off your users with some free trial days, then you must also have their customer object and subscription created in Stripe at the time of signing up. You have two options. You can use the Billflow Pricing Page & Signup Form with your user signup form, or simply use [Stripe's APIs](https://stripe.com/docs/api). You can make two API calls to Stripe to create the customer object and then subscribe the customer to a new subscription with a free trial. Once created, the Billflow Customer Portal will let them manage their subscription and add payment information before trial is over.

#### Paid Upfront

If you are asking your customers to pay you upfront prior to getting access to your product, then you have a few options. You can use the Billflow Pricing Page & Signup Form with your user signup form, you can simply use [Stripe's APIs](https://stripe.com/docs/api), or you can use [Stripe Hosted Payment Pages](https://stripe.com/docs/payments/checkout).

## User Authentication

Most SaaS products have some kind of user management system. This is how you will register and authenticate users into your application. Billflow works with any Auth system, custom or 3rd party.&#x20;

We use the user's email *or* Stripe customer\_id to validate your user's identity prior to showing them the billing data.

## Store data needed on user

We recommend you store the Stripe *subscription ID*, the *tier name*, and the *subscription status* in your database for each user. Optionally, you can also store the Stripe customer ID or the entire [subscription object](https://stripe.com/docs/api/subscriptions/object) as returned from Stripe. You can use this information to restrict access to features or the app all together. You can restrict initial access by checking if the *subscription ID* or *status* is set, then use *status* to determine if they are active, trialing, cancelled, and more. *Tier* can be used to restrict access to features or limit usage based on the tier the user is on.

If you are doing metric based billing, you will also want to store the [subscription item](https://stripe.com/docs/api#subscription_items) ID for each metric you have available on your service & tier. The [subscription item](https://stripe.com/docs/api#subscription_items) ID is used for updating the metric later.

In order to keep this data up to date, you need to listen for Stripe webhook events. Continue on to learn more.

## Create Post signup process

Populating the data you need in the first step is done by using the handleResponse function in the subscription portal front-end code. In order for the changes to be immediate, we use handleResponse as opposed to webhooks for subscription creation and resubscribe. If you process cancellations immediately instead of at the end of a billing period you will want to update your user with handleResponse as well.&#x20;

Simply run the code for your user update or make an API call based on the event in handleResponse. The response for that event is the [subscription object](https://stripe.com/docs/api/subscriptions/object) and from that you will be able to determine the subscription id, customer id, service & tier name from the metadata (Billflow automatically adds the product metadata to subscriptions), and the subscription status.

```javascript
handleResponse: async function({event, response}){
    if(event === "create_subscription" || event === "resubscribe"){
        console.log("Activating account!", response);
        let activationResponse = await fetch("/activate", {
            method: "POST",
            credentials: "include",
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                subscription_id: response.id
            })
        }).then(response => response.json());
            console.log("response from server - ", activationResponse);
        }
    }
} 
```


# Using Stripe Webhooks

Listening for Stripe webhooks

## Overview

In order to keep your database in sync with Stripe subscription events, we need to listen to Stripe webhooks. When free trials end, cancellations, upgrades, and downgrades come through you will be notified and change the user status in your system. This allows to you restrict access, change functionality, or provide notifications to the users, whether the changes are made by the user from the Customer Portal, or by an Admin from the Stripe Dashboard. Here's what we'll go over:

**Events needed.** Stripe provides tons of events, but we only need to listen to some to complete our billing flow. &#x20;

{% hint style="info" %}
If you are using a platform plugin, this step could be different for you. Make sure to check out the [integrations](/no-code-integrations/no-code-app-builders) for specific instructions.
{% endhint %}

## Events needed

Here's a list of our recommended events to listen to. Read [here](https://stripe.com/docs/api/events/types) for a full list of Stripe available events, and [here](https://stripe.com/docs/webhooks) for more information on implementing Stripe webhook listener on your app.

#### Necessary

| Event Name                                                                                                          | Description                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [customer.subscription.created](https://stripe.com/docs/api/events/types#event_types-customer.subscription.created) | Occurs whenever a customer is signed up for a new plan. Use it to ensure the data was populated in your user system by the handleResponse method.                                                                         |
| [customer.subscription.deleted](https://stripe.com/docs/api/events/types#event_types-customer.subscription.deleted) | Occurs whenever a customer's subscription ends. Use this to update the user's subscription status.                                                                                                                        |
| [customer.subscription.updated](https://stripe.com/docs/api/events/types#event_types-customer.subscription.updated) | Occurs whenever a subscription changes (e.g., switching from one plan to another, or changing the status from trial to active). Use this to update the user's subscription status for upgrades/downgrades and trial ends. |

#### Nice to haves

| Event Name                                                                                                                          | Description                                                                                                                                                                                                     |
| ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [customer.source.created](https://stripe.com/docs/api/events/types#event_types-customer.source.created)                             | Occurs whenever a new source is created for a customer. Use for sending notifications to your user.                                                                                                             |
| [customer.source.expiring](https://stripe.com/docs/api/events/types#event_types-customer.source.expiring)                           | Occurs whenever a card or source will expire at the end of the month. Use for sending notifications to your user.                                                                                               |
| [customer.source.updated](https://stripe.com/docs/api/events/types#event_types-customer.source.updated)                             | Occurs whenever a source's details are changed. Use for sending notifications to your user.                                                                                                                     |
| [customer.subscription.trial\_will\_end](https://stripe.com/docs/api/events/types#event_types-customer.subscription.trial_will_end) | Occurs three days before a subscription's trial period is scheduled to end, or when a trial is ended immediately (using `trial_end=now`). If you have a free trial, use for sending notifications to your user. |
| [invoice.payment\_failed](https://stripe.com/docs/api/events/types#event_types-invoice.payment_failed)                              | Occurs whenever an invoice payment attempt fails, due either to a declined payment or to the lack of a stored payment method. Use for sending notifications to your user or restricting access.                 |

## Setting up Stripe to send events to your app

You can add your app as an endpoint from the [Stripe Dashboard](https://dashboard.stripe.com/account/webhooks). You should set up an 'Account' type webhook endpoint and configure the events listed above. For more details on setting up your app as an endpoint, read [here](https://stripe.com/docs/webhooks/setup#add-endpoint-dashboard).&#x20;


# Change Style

How to modify the look of Billing Pages

The look of all billing pages is highly customizable so that they integrate seamlessly with your website/app. Using CSS, colors and fonts can be changed, and content can be added or removed. Below are the steps to change the style.

{% hint style="info" %}
Easy style changes coming to the dashboard soon!
{% endhint %}

## Step 1: Set Default Colors

Navigate to your billing page on the Billflow dashboard. There you will see a section for Design changes. Use this section to set your default colors. You can also add custom CSS here. To learn more about adding custom CSS, continue reading below.

![Dashboard Design Options](/files/-MMRiuyVbkEkE7hMopu-)

## Step 2: Apply Custom Styling

You can add custom CSS to the 'CSS Modifications' section of the Design tab.&#x20;

### Step 1: Determine class

The easiest way to determine the CSS class of the piece you wish to change is to inspect element with your browser. Right click on the thing you want to change and select Inspect. We can see the class name of this button is *.servicebot-btn-primary*

![Inspecting Billing Page Style](/files/-MJ36G5Miesh-ZiGt1-9)

### Step 2: Override style

Now we can override the style. You can do this within your browser then copy the style to your CSS file.

![](/files/-MJ36hmEnleMLDbBeVaa)

## Templates

Below are examples & templates for billing page style changes. Just add the CSS to your project to add to your billing page.

{% content-ref url="/pages/-MGp-uhmJJtALiI7giMf" %}
[Plan Picker Style Templates](/how-to/change-style/plan-picker-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp-woNQpzKtTivzid\_" %}
[Customer Portal Style Templates](/how-to/change-style/customer-portal-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp0-9miuJk6ZYPbdIy" %}
[Pricing Page Style Templates](/how-to/change-style/pricing-page-style-templates)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp022oJ-7-OcCyEsXR" %}
[Checkout Form Style Templates](/how-to/change-style/checkout-form-style-templates)
{% endcontent-ref %}

&#x20;


# Plan Picker Style Templates

Plan Picker Style Templates & Examples

{% hint style="warning" %}
CSS Style not working for you on your site? Try to add **!important;** to the CSS values.
{% endhint %}

## Add Features to Plans

One popular thing to do is to add tier descriptions or features to the Plan Picker.

{% hint style="info" %}
Adding feature to Plans will soon be done from the dashboard
{% endhint %}

{% embed url="<https://codepen.io/kmidkiff/pen/vYOXKOX>" %}

## Change Font & Color

Simple change of Colors & Fonts

{% embed url="<https://codepen.io/kslung/pen/qBOXeWW>" %}

## Show Discounts

Show annual discount on Interval tab & plans

{% embed url="<https://codepen.io/kmidkiff/pen/JjdRKbd>" %}

## Modify Signup Button Text

This example does not use CSS, but the Language Internationalization feature. Learn more about that [here](/how-to/internationalization/support-multiple-languages#advanced-usage).

{% embed url="<https://codepen.io/kmidkiff/pen/qBOxXez>" %}


# Customer Portal Style Templates

Customer Portal Style Templates & Examples

{% hint style="warning" %}
CSS Style not working for you on your site? Try to add **!important;** to the CSS values.
{% endhint %}

## Hide different sections of the customer portal

If you have any sections of the customer portal you do not want visible, or you only want to show one section, you can do this with CSS. Each section of the customer portal has a CSS tag that can be used to hide that functionality. Below is the CSS to hide every section of the customer portal. You can use this to hide the section you want from view, and add it to the CSS section of the Design editor.

```
.bfc.view_all_subscriptions, .bfc.summary, .bfc.details, .bfc.action_group, .bfc.billing_info, .bfc.update_card, .bfc.invoices{
    display: none;
}
```


# Pricing Page Style Templates

Pricing Page Style Templates & Examples

{% hint style="warning" %}
CSS Style not working for you on your site? Try to add **!important;** to the CSS values.
{% endhint %}

## Add Features to Plans

One popular thing to do is to add tier descriptions or features to the Plan Picker.

{% hint style="info" %}
Adding feature to Plans will soon be done from the dashboard
{% endhint %}

{% embed url="<https://codepen.io/kmidkiff/pen/vYOXKOX>" %}

## Change Font & Color

Simple change of Colors & Fonts

{% embed url="<https://codepen.io/kslung/pen/qBOXeWW>" %}

## Show Discounts

Show annual discount on Interval tab & plans

{% embed url="<https://codepen.io/kmidkiff/pen/JjdRKbd>" %}

## Modify Signup Button Text

This example does not use CSS, but the Language Internationalization feature. Learn more about that [here](/how-to/internationalization/support-multiple-languages#advanced-usage).

{% embed url="<https://codepen.io/kmidkiff/pen/qBOxXez>" %}


# Checkout Form Style Templates

Checkout Form Style Templates & Examples

{% hint style="warning" %}
CSS Style not working for you on your site? Try to add **!important;** to the CSS values.
{% endhint %}

## Simplified Signup

This is a very streamlined checkout form. It utilizes the default Stripe Element style.

{% embed url="<https://codepen.io/kmidkiff/pen/VwjwQgP>" %}

## Modify Signup Button Text

This example does not use CSS, but the Language Internationalization feature. Learn more about that [here](/how-to/internationalization/support-multiple-languages#advanced-usage).

{% embed url="<https://codepen.io/kmidkiff/pen/OJXJQzx>" %}


# Update Pricing

How to modify your pricing in Stripe & Billflow

## How to update prices

In order to update your prices, create new Prices in Stripe for each that need updating and archive old Prices. You can only edit a Price's price if it has not been used to create a subscription.

## Create new Price

Go to the Stripe dashboard and select a Product that is part of your service. Click "Add another price" to create a new plan at the price you want.&#x20;

![Create another price](/files/-MIykxN18k2Y3kQqlfXX)

## Archive old Price

Then, go back to the product and archive the old price by clicking "..." and "Archive price".&#x20;

![Archive Price](/files/-MIymi4CweEgHmtGA9HA)

Your Billing Pages will automatically update for the new pricing and customers already subscribed will remain on their current pricing. They will automatically be grandfathered in and only change their price if they change their plan to the new price or cancel and resubscribe. This process will keep you from generating unnecessary products in Stripe and is easy to maintain.


# Use Coupons

Allow customers to apply coupons

## Overview

Discounts are a great way to increase signups, conversion and retention. The easiest way to handle promotions and discounts is to send out coupon codes. Coupon codes can be created from the Stripe dashboard, then customers can enter them from checkout or add them to existing subscriptions on the customer portal.

![Coupon button on Checkout Form](/files/-MJ3d0gL3E_87Fbc3SyG)

![Coupon button on Customer Portal](/files/-MJ3d87R7i8n0YXCSk6T)

![Button Pop-up](/files/-MJ3dFMwc_Ut1pZz_Nvu)

Below are the steps to enable this feature.

## Create Coupon in Stripe

Create a new coupon in Stripe. Note that the Coupon ID is what customers need to enter to redeem the coupon, not name. Stripe 'customer-facing' coupon codes or Promo Codes can also be used to redeem a coupon.

![Coupons on Stripe Dashboard](/files/-MJ3l2Zx8uyQUCW9nn1j)

![Creating a coupon, note ID used for redeeming](/files/-MJ3l866QnB8Keet7tNr)

![Promo codes also able to be used](/files/-MJ3lF0ZNxMCzo4epzua)

## Enable on Billing Page

Go to your billing page and enable the option for coupons.

![](/files/-MJ3dWFA7f6bpDPSsd17)

##


# Enable Quantity Management

Allows customers to manage the quantities of their subscription

## Overview

Quantity management allows your customers to select the quantity of a product they want on checkout and/or manage that from the Customer Portal. This is great for unit-based pricing models where you charge per seat, user, or other unit.&#x20;

![](/files/-MQn-VSSU6RX-QkT31Rf)

![](/files/-MQn-bJRma9hVMVKdi9S)

![](/files/-MQn0Ex_Dahy2oCo5siX)

![](/files/-MQn0TViCKGhphhPKMwE)

Below are the steps to enable this feature.

## Configure Stripe

### Add Metadata

To allow changing of quantities, you need to add the following metadata to your Stripe Products

| Metadata                    | Description                                         |
| --------------------------- | --------------------------------------------------- |
| sb\_quantity\_enabled: true | allow change quantity in pricing /signup and portal |

![Stripe Product Metadata Settings](/files/-MJ3OhVrhgdjhpmDEz3X)

### Set Unit Label

To allow changing of quantities, you need to have a unit label on your Stripe Product. This tells Billflow that the product is used for unit-based billing.

![Setting Unit label on Stripe Product](/files/-MJ3RXgs9GCDf-ehBkNr)

## Enable on Billing Page

Go to your billing page and enable the option to allow quantity management. There you can also set the minimum, maximum, and steps of the quantity section.

![](/files/-MMRja-NgzPY0yQc0Khf)

## Additional Settings

In addition to enabling the quantity management feature, you can add the following settings to control some behaviors.

| Key  | Type   | Required? | Default          | Description                                                                                                                                                                                                                  |
| ---- | ------ | --------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| min  | number | no        | 0                | <p>Default is 0</p><p>Sets the minimum that your customer can set the quantity value. </p><p>For example: 10 users. </p><p>Use case: you do not want someone to set it to 0 or -1 or you have a minimum signup quantity.</p> |
| max  | number | no        | Stripe Max Limit | <p>Sets the maximum that your customer can set the quantity value.</p><p>For example 100 users. </p>                                                                                                                         |
| step | number | no        | 1                | <p>Default is 1</p><p>If set to 10, the plus and minus buttons will increase or decrease the quantity by 10 when clicked.</p>                                                                                                |

```javascript
"options":{
   "behavior":{
      "quantityManagement":{
         "unit":{
            "email":{
               "min":10,
               "max":5000,
               "step":50
            }
         }
      }
   }
}
```


# Enterprise Sales Flow

There are a handful of ways to handle enterprise or one-off sales with Stripe and Billflow. They allow you to create client-specific payment amounts, send them invoices payable by card, ACH, or SEPA, and also be able to view those invoices from the Billflow customer portal. Here we will go through the most common process. If this is does not fit your processes, let us know and we can offer other options.

### Step 1: Create a Customer

The first step after determining price point is to create a customer in Stripe. Log into your Stripe dashboard and select Customers and New. (This step can also be done via the Stripe API if you want a user to signup from your app first)

![](/files/-MIyr54oTDOjAOg_V2zV)

Fill out the details you have about the customer. If you have their payment information, you can add it directly when creating the customer. No problem if not, we can collect it later.

### Step 2: Create a subscription or one-time invoice

Next you will create a subscription or invoice for the customer. The only difference being is that subscriptions are for recurring payments whether that be monthly, annual or something in between, and invoices are just for a one-time payment.

#### Subscription

Select the customer you created and choose "Create Subscription"

![](/files/-MIyr8j5TXY1B7CsYVIv)

To create a subscription you must have a Product to define its price. Create a new product or use an existing one.

![](/files/-MIyrBSaUY25X-sncIBr)

#### Invoice

Select the customer you created and choose "Create Invoice"

If you are creating the same price point many times, we recommend creating a Product in Stripe for that price. Or you can continue to create one-off amounts every-time.

### Step 3: Send Invoice

Now you once again have the option to add a payment method or for Stripe to email them with a hosted payment form. You can turn on CC, ACH, and SEPA if it's available for your account.

![](/files/-MIyrE2Pc99UF4Fw_1UT)

Select Start Subscription or Create Invoice

### Payment from Stripe hosted email

Stripe will now email your client with a hosted payment page that looks like the following

![](/files/-MIyrGciUjx_CToGt_W1)

The customer can now select "Pay this invoice" which will take them to the Stripe hosted payment page

![](/files/-MIyrK0e5sxoahMDSm5M)

It gives them the option to pay via CC, ACH, and other payment methods if enabled.

![](/files/-MIyrN4242wEDqXBXeWj)

### Payment from Billflow Customer Portal

The subscription and invoice will also appear in the customer portal if you have it installed in your website or app. They can add CC information or click the 'Pay Now' button to be directed to the same hosted Stripe payment page that is sent in the email.

![](/files/-MQn0s9gEm7HkPc39EFn)

![](/files/-MIyrRw-ACZ_VORjyWcE)

From this point, the customer and subscription can be managed from the Stripe dashboard by you, or the customer can self-service their subscription management from the Billflow customer portal. As an admin you are able to add additional charges, update the subscription or invoice amount, perform refunds, and cancel subscriptions.


# Cancellations/Payment Failures

How to handle cancelations and payment failures

Churn has a massive impact on subscription businesses, many times reducing churn is the single best thing a business can focus on to increase revenue. Billflow, together with Stripe, has some great features to help you reduce churn.

{% content-ref url="/pages/-MGp0BuN2FwXvm8gxM\_-" %}
[Set up Cancellation Feedback](/how-to/cancellations-payment-failures/set-up-cancellation-feedback)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp0ImlngVX1h5ChEBL" %}
[Configure Dunning Emails](/how-to/cancellations-payment-failures/configure-dunning-emails)
{% endcontent-ref %}


# Set up Cancellation Feedback

How to gather cancellation feedback

A great way to improve your product and service is to figure out why customers leave. Billflow makes it super easy to get feedback when a customer chooses to cancel their subscription.&#x20;

## Enable Cancellation Feedback

Here's how to enable that on the Customer Portal:

Make sure you have turned on **Enable cancellation** and **Ask for cancellation reason** from the billing page editor.

![Cancellation Options on dashboard](/files/-MJ-zv1c50W3fMvS0E8V)

With these enabled, when your customers select the cancel action, they will see the following pop-up.

![Cancelation Feedback pop-up](/files/-MJ0-Y4muZMfSW_jN8JW)

## Show a custom survey on cancellation

Using the handleResponse option and the Typeform modal embed, you can show a survey to users on cancellation to learn more about why the cancelled. Check out the example!

{% embed url="<https://codepen.io/kmidkiff/pen/XWmoJyG>" %}


# Configure Dunning Emails

Stripe can be configured to send emails to your customers when a failed payment goes through. On this email there is a link for the customers to update their payment information. This link can be set to the page where you have the Billflow Subscription Management Portal, and from there they will be able to update their payment details. Follow the steps below to enable that.

## Step 1: Turn on Emails

Go to <https://dashboard.stripe.com/settings/billing/automatic> & turn on Customer Emails for failed payments.

![Turn on email on Stripe Dashboard](/files/-MIyiDYe3YTfXvDr-IIs)

## Step 2: Configure URL

Click on the eye icon and paste in the URL where you have your Subscription Portal embedded.

![Configure email link on Stripe Dashboard](/files/-MIyiVUlTQkD6NEsK8fJ)

Done! You're all set. Now when a customer has a failed payment, they'll receive an email with a link to update their payment information.


# Automated emails

You can configure automatic emails to be sent to your customers when billing related events happen like an invoice being finalized, a free trial ending, a payment failing and many more. These come out-of-the-box with your Stripe account and below is where to configure those.&#x20;

{% hint style="info" %}
Stripe will not send emails in Test-Mode. Enable Live-Mode to fully test automated emails.
{% endhint %}

General email settings [here](https://dashboard.stripe.com/settings/emails)

Configure free-trial, invoice, and failed payment-emails [here](https://dashboard.stripe.com/settings/billing/automatic)

For more detailed instructions on dunning emails, continue reading [here](/how-to/cancellations-payment-failures/configure-dunning-emails)

If there are notifications you want to send your customers that are not provided out-of-the-box, you can set that up by listening to webhooks. Services like [Zapier](https://zapier.com/) are an easy and no-code way to listen to Stripe events and perform actions like send an email when the event has occurred.&#x20;


# Internationalization

Internationalizing your product

Billflow allows you to support both multiple languages and multiple currencies for taking your product global.

## Support multiple currencies

Billflow supports all currencies [supported by Stripe](https://stripe.com/docs/currencies). Read the following guide for detailed steps on adding multiple currencies.

{% content-ref url="/pages/-MGj2iLYVg6Pi8pjzDQd" %}
[Support multiple currencies](/how-to/internationalization/support-multiple-currencies)
{% endcontent-ref %}

## Support multiple languages

By default, Billflow will automatically translate the billing pages to the user's default browser language setting. A default language can also be set so only one is shown. Read the following guide for detailed steps and advanced usage of language settings.

{% content-ref url="/pages/-MGj2gTC6Z4e26tPdfiz" %}
[Support multiple languages](/how-to/internationalization/support-multiple-languages)
{% endcontent-ref %}


# Support multiple currencies

How to support multiple currencies

Looking to go global? You can create billing pages for each currency you want to offer, even offering different prices to different regions. Below are the steps to support multiple currencies.

## Create Products in Stripe

You should create a Service for every currency you are planning to sell. That means creating products just like your standard offering, but adding a different metadata tag for sb\_service. It's easiest to simply hyphenate the product names and sb\_service name with the currency abbreviation. Go [here](/how-to/setup-pricing) for in depth steps of setting up pricing.

![Creating Stripe Product for new currency](/files/-MJ3v4Wu9-Dpqg-AhsEH)

Set the currency and price to the new amount and save.

![Setting currency and Price](/files/-MJ3vD4o0Sc3O2cEzARF)

## Create new Billing Page

Now you just need to create a new billing page and set the Service to the newly created service. Embedding will be the same process and you will see the new currency on the billing pages.


# Support multiple languages

Features and advanced usage of language settings

## How does it work?

Our embeds will automatically detect your end user's browser language preference to determine what language the embed will render in. If the language is not supported by our embed, a default language will be displayed. The default language is English US.

## Current supported languages

| Language / Locale    | Support | Code  |
| -------------------- | ------- | ----- |
| English US           | Default | en    |
| Chinese (Simplified) | Yes     | zh    |
| Danish               | Yes     | da    |
| French               | Yes     | fr    |
| German               | Yes     | de    |
| Italian              | Yes     | it    |
| Polish               | Yes     | pl    |
| Spanish              | Yes     | es    |
| Norwegian            | Yes     | no    |
| Brazilian Portuguese | Yes     | pt-BR |

{% hint style="info" %}
More languages are coming soon! You can contribute and help us provide the embed in more languages by translating the [JSON fi](/how-to/internationalization/support-multiple-languages#translation-files)[es](/how-to/internationalization/support-multiple-languages#translation-files) into the language that you support as well. Just send us the translated files via the Intercom chat below.
{% endhint %}

## Dashboard

On the Billflow dashboard, you will find the settings form for each embeds that looks like the following screenshot. In the following sections, we describe the with an example value for each settings field.

![](/files/-MJ-oAgkJvpVGmg6vGfw)

### Custom text override by key values

This is a way for you to change some text for the language you chose. You can refer to the [language files](/how-to/internationalization/support-multiple-languages#translation-files) for your desired language to find the right key-value pairs and change the value to override the text.

![You can put your custom translation in the box highlighted in this screenshot](/files/-MWfeNlLoO2t89wJFK6p)

For example:&#x20;

```javascript
{
    "SectionTitle_Pricing": "欢迎，请选择一个计划开始！"
}
```

### Backend URL

A backend for the custom translation files that you'd like to provide.&#x20;

```
https://storage.googleapis.com/your-i18n-custom/{{lng}}/{{ns}}.json"
```

## Advanced Usage

The configuration options do not need to be changed at all for Internationalization to work, but it does unlock the ability for you to pass in your own language file, or change the default text in the embeds easily.

Using this functionality you can also change the text of the Billflow pages for your default language. Use the keys in the [translation files](/how-to/internationalization/support-multiple-languages#translation-files) to lookup the text you want to change, and pass in your desired wording like so:&#x20;

{% embed url="<https://codepen.io/kmidkiff/pen/qBOxXez>" %}

### Embed configuration options

| Property Name                | Type    | Required | Description                                                                                                                                                                                                                                                                                                        |
| ---------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| i18n.defaultLng              | string  | no       | Changes the default language of the embed, overriding user browser preference. Example: "zh"                                                                                                                                                                                                                       |
| i18n.resources               | array   | no       | An array of resource objects. Each object is a resource for a language and namespace.                                                                                                                                                                                                                              |
| i18n.resources\[0].lng       | string  | yes      | The language of this resource object                                                                                                                                                                                                                                                                               |
| i18n.resources\[0].ns        | string  | yes      | The namespace of this resource object                                                                                                                                                                                                                                                                              |
| i18n.resources\[0].resource  | object  | yes      | <p>The resource object with key value pairs to provide a translation string to the language and namespace defined, where value is the translated string.</p><p>You can find the appropriate keys by looking through one of the <a href="/pages/-MGj2gTC6Z4e26tPdfiz#translation-files">English JSON files</a>.</p> |
| i18n.backend                 | object  | no       | You can use a backend, a file system of your own such as AWS s3 or Google cloud storage to provide translation files.                                                                                                                                                                                              |
| i18n.local\_storage\_caching | boolean | no       | To disable use of browser local storage for caching i18n files, set this property to `false`, the default is true. Use this option if your application runs in an environment where local storage is not permitted.                                                                                                |

### Backend usage

You can provide a backend URL to the configuration, our embed will automatically fetch each file at render time.&#x20;

{% hint style="info" %}
**Important!**

Make sure CORS is enabled for dashboard.billflow\.io and your website/webapp's domain on your server.

Translation files are cached for 3 hours in browser, when implementing a custom language file, please use a fresh Incognito window to see the changes.
{% endhint %}

Example: Using google cloud storage

1. Create a bucket named your-i18n-custom&#x20;
2. Create a folder structure and files as follows (we are using French as an example)
   1. fr
      1. common.json
      2. portal.json
      3. pricing.json
      4. custom.json
3. In each file, you can copy the [English JSON files](/how-to/internationalization/support-multiple-languages#translation-files) contents and do your translation.&#x20;

{% hint style="info" %}
You can even use this way to define your own custom English version, if for any reason you would like to change how your embed text is rendered in English. For example, if you want to change the Pricing page heading to say "Welcome, please pick a plan to start!" instead of the default text "Pricing", you can do that this way.
{% endhint %}

### Example configuration

```javascript
// Example i18n configuration

"options": {
   "i18n":{
      "defaultLng":"zh",
      "resources":[
         {
            "lng":"zh",
            "ns":"custom",
            "resource":{
               "SectionTitle_Pricing":"欢迎，请选择一个计划开始！"
            }
         }
      ],
      "backend":{
         "loadPath":"https://storage.googleapis.com/your-i18n-custom/{{lng}}/{{ns}}.json"
      }
   }
}
```

### Translation files

These are the default English text that we are using in our embeds, you can download them and translation / change them the way you like it, then use your version in the embed!

1. <https://storage.googleapis.com/servicebot-i18n/en/billflow.json>
2. <https://storage.googleapis.com/servicebot-i18n/en/common.json>
3. <https://storage.googleapis.com/servicebot-i18n/en/portal.json>
4. <https://storage.googleapis.com/servicebot-i18n/en/pricing.json>
5. <https://storage.googleapis.com/servicebot-i18n/en/checkout.json>
6. <https://storage.googleapis.com/servicebot-i18n/en/moment.json>


# Upgrade to new Billing Pages

Upgrade steps to turn your current Billflow embeds to the new Billing Pages

Have you already integrated with Billflow using the embed snippet with config options? No worries, your current integration will work fine. The benefit that the new Billing Pages provides is that it hosts your configs so you never have to go into code to update them. Now, all updates are done straight from the Billflow dashboard. Follow the steps below to upgrade to the new Billing Pages.

## Step 1: Create Billing Page

On the dashboard you will now find 5 options for billing pages. Create a new billing page for your needs.

#### Pricing Page: Same as the previous pricing page type. Intended for marketing site.

#### Checkout Form: Same as the previous Signup/checkout form.&#x20;

#### Plan Picker: New type intended for plan selection in-app and optionally showing customer portal for subscribers. Use this if you are using the customer portal and signing users up with it as well.

#### Customer Portal: Same as the previous customer portal type. Intended for subscription management in-app. Use this if you are using just the customer portal portal currently.

#### Invoice Portal: New type that is similar to the customer portal. Intended for viewing invoices in-app.

## Step 2: Set options to match your config

Go to your current embed snippet and turn on the options on the billing page to match what you have configured on your embed snippet. Options on the dashboard are worded naturally so it will be intuitive to pick the options you have configured from your snippet.&#x20;

Save once you are done and you will have the option to embed.

{% hint style="info" %}
You can still pass in configs to the new snippet just as before. So any dynamic data you will pass in the same way like the commonly used 'metadata' option. Same for handleResponse.
{% endhint %}

## Step 3: Update your current embed snippet

Copy your new embed snippet. It should look familiar, it has an addition of a billing\_page\_id. Necessary dynamic values will still be there like email and hash, but all other options can now be set on the dashboard. Paste your new snippet in.

{% hint style="warning" %}
Secure Setup remains the same
{% endhint %}

```markup
<div id="billflow-embed"></div>
    <script>
        window.billflowSettings = {
    "billing_page_id": "7nTEgMCYPYSHvCOdwqyo",
    "email": "// change this to your customer's email",
    "hash": "// change this to your hash generated by your server using secured setup"
};
        (function () { var s = document.createElement('script'); s.src = 'https://js.billflow.io/billflow-embed.js'; s.async = true; s.type = 'text/javascript'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })();
    </script>
```


# Record Usage

How to send quantity updates or metered usage to Stripe

If your pricing strategy included usage-based pricing, such as per API, per requests, per orders, etc, you might want to record the actual usage of your customers so they will be billed properly at the end of each cycle. This is done through Stripe. Stripe allows you to record the usage of a customer to their subscription through their powerful APIs.&#x20;

## Record Units in Stripe

If you are using recurring quantities and want to change the number of units a customer is at like “per-seat licensing”, you need to update the quantity on the Plan.

For an in depth guide on handling subscription quantities check out [this guide](https://stripe.com/docs/billing/subscriptions/quantities).

## Record Metered Usage in Stripe

There is a [Stripe API call for creating a usage record](https://stripe.com/docs/api/usage_records/create), which is how you add to the metric you're billing against. You must store the [subscription item](https://stripe.com/docs/api#subscription_items) ID on your database because it is used to update the usage of a metric. Any metrics you update will be reflected in the Billflow Subscription Management Portal for your customers to see.&#x20;

For an in depth guide on handling metric based check out [this guide](https://stripe.com/docs/billing/subscriptions/metered-billing).


# VAT & Taxes

Setting up taxes

## Overview

Taxes are not fun but they need to be handled. Stripe & Billflow can make it easier for you, following are the steps to collect Taxes.

## Configure in Stripe

For more detailed configuration guides and how-tos in Stripe check out the docs [here](https://stripe.com/docs/tax).&#x20;

### Enable in Stripe

Start by enabling taxes on your Stripe account. You can go to <https://dashboard.stripe.com/settings> and add the Tax feature.

### Set up Business information in Stripe Tax Settings

For more general tax details check out Stripe's guide [here](https://stripe.com/guides/introduction-to-us-sales-tax-and-economic-nexus).&#x20;

![](/files/-Me_fhM4PCp-Zz-El3bp)

### Set up Registrations in Stripe Tax Settings

![](/files/-Me_fuSr8e4lcIGbHW2U)

### Set Tax code on Stripe Products

If you haven't been using tax before, your Stripe products need a Tax Code set.

![](/files/-Me_gPNBuQk_ywRsVdty)

### Set Tax behavior exclusive on Stripe Prices

Set product behavior to include tax, or to exclude tax.

![](/files/-Me_ga89CMuzgIepwcTr)

## Configure in Billflow

Enable Automatic Taxes on Billfow billing page Checkout Form settings. You can also enable Tax ID to be asked on checkout there. Make sure you are on v3 or greater!

![](/files/-Me_hKwXarYHoNWpCsP7)

{% hint style="info" %}
Do not set a default tax rate on the billing page, it will conflict
{% endhint %}

### Embed and view checkout form

Make sure your IP and/or billing address when viewing checkout form is in a country registered in your Stripe Tax settings. You should then see the checkout automatically calculate the tax!

![Checkout with tax added](/files/-Me_hsV1KFYPfN9DST5n)


# Indian Recurring Payments

This is in regard to [Important updates to RBI regulations on recurring card payments in India](https://support.stripe.com/questions/important-updates-to-rbi-regulations-on-recurring-card-payments-in-india)

It only applies to customers located in India. Two changes need to be made for customers in India. One is to set all new subscriptions created to "Send Invoice" instead of "Charge Automatically" and to set the days until due option. The second change is to update existing subscriptions for Indian customers.&#x20;

## Options for new subscribers

Set the "Days Until Due" option in the Checkout Form settings in the Billflow Dashboard. Billflow will automatically set the subscription payment to be via send invoice instead of charge automatically for customers located in India.

![Billflow dashboard option](/files/Dd8unLSP38PJazTHYLb0)

## Script for existing subscribers

You will need to update existing subscriptions for Indian customers. You can do this from the dashboard by changing the payment option from automatically charge to send invoice. If you have many customers, you can run the script we have provided below. You can set 'days\_unti&#x6C;*\_*&#x64;ue' to a value you need.

```
async function main() {
    const stripe = require("stripe")("your_stripe_secret_key")
    for await (let subscription of stripe.subscriptions.list({ expand: ["data.default_source", "data.default_payment_method", "data.customer.default_source"] })) {
        if ((subscription.default_source && subscription.default_source.country == "IN")
            || (subscription.default_payment_method && subscription.default_payment_method.card && subscription.default_payment_method.card.country == "IN")
            || (subscription.customer.default_source && subscription.customer.default_source.country == "IN")) {
            console.log("FOUND AN INDIAN CUSTOMER, moving to send_invoice instead of charge_automatically", subscription.customer.id);
            stripe.subscriptions.update(subscription.id, {
                collection_method: "send_invoice",
                days_until_due: 20
            })
        }
    }
}
main()
```


# No-code App Builders

The easiest & fastest way to start

The easiest & fastest way to get started is to use a plugin for a no-code platform. Billflow provides plugins to make the installation and integration a breeze. Check out the available plugins below.

{% content-ref url="/pages/-MGTTFN1Y1ptcNE6YYvj" %}
[Bubble](/no-code-integrations/no-code-app-builders/bubble)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTI8\_MPZ4mQAceQaf" %}
[Webflow](/no-code-integrations/no-code-app-builders/webflow)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTKMxtuPdZ2LBxwSa" %}
[WordPress](/no-code-integrations/no-code-app-builders/wordpress)
{% endcontent-ref %}

{% content-ref url="/pages/-MKfZAxfqkrm-ZMWt8Xf" %}
[Notion](/no-code-integrations/no-code-app-builders/notion)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTTNWH\_3Wo7uOWC7Wo" %}
[Drupal](/no-code-integrations/no-code-app-builders/drupal)
{% endcontent-ref %}


# Bubble

Bubble Plugin Instructions

## Description

The Pricing Page element in Bubble connects Bubble to the Billflow [Pricing Embed](https://www.servicebot.io/pricing-portal). You can use all the functionality of Billflow along with some useful Bubble events to perfect your billing system within a Bubble application.&#x20;

{% embed url="<https://www.youtube.com/watch?v=GbaixVS6E4I>" %}

## Supported Pages

* Plan Picker
* Checkout Form
* Customer Portal
* Pricing Page
* Invoice Portal

## Using the pricing page element in Bubble

### Drag and drop

After installing the Billflow plugin for Bubble, drag the "Pricing Page" element from the Visual Elements Section, resize the element to your liking.

![](/files/-MJ3xuO5F3S0rPb8e347)

### Add Billflow configuration JSON

Go to your Billflow dashboard and customize the pricing page to your specifications.&#x20;

Once fully configured, click "Embed Pricing Page", and copy the code in the "Bubble" section, and past in the configurationJSON section within Bubble

![](/files/-MJ3ySZvKigFLVrXfH-k)

### How to prompt for a password

To prompt for a password if you want users onboarded using Billflow, make sure to have this option enabled:

![](/files/-MJ3ymXMCQpBAwoztNmx)

## Pricing page events and states

![](/files/-MJ3yr-o_vusS2Zcfboq)

With the element, you can call workflows based on the following events, with the following states available within each:&#x20;

**User Subscribed** - Triggered when a user subscribes using the Pricing Embed\
**User Subscribed States:**

* **user\_subscribed\_email -** The email entered on the form
* **stripe\_subscription\_id -** The ID of the [Stripe Subscription](https://stripe.com/docs/api/subscriptions/object) created
* **stripe\_customer\_id -** The ID of the [Stripe Customer](https://stripe.com/docs/api/customers/object) created
* **user\_subscribed\_password -** If promptPassword option is true, the password
* **user\_subscribed\_tier -** [**The sb\_tier**](https://docs.servicebot.io/subscription-portal/setup-your-stripe-account#metadata) **of the subscription that was created**
* **user\_subscribed\_status -** The [subscription status](https://stripe.com/docs/api/subscriptions/object#subscription_object-status) as it is in Stripe

## Using the subscription portal element in Bubble <a href="#using-the-subscription-portal-element-in-bubble" id="using-the-subscription-portal-element-in-bubble"></a>

### Drag and drop <a href="#drag-and-drop" id="drag-and-drop"></a>

After installing the Billflow plugin for Bubble, drag the "Subscription Portal" element from the Visual Elements Section, resize the element to your liking.

![](https://gblobscdn.gitbook.com/assets%2F-LkAdq4qKmsg1iQv3yZn%2F-M2dm4uuUhczPg2c_eXK%2F-M2tXJe1s3qKmzIcItxt%2FScreen%20Shot%202020-03-20%20at%2012.31.19%20PM.png?alt=media\&token=69b74005-63c5-4e7e-ba68-d77a5c829838)

### Set up Authorization HMAC <a href="#set-up-authorization-hmac" id="set-up-authorization-hmac"></a>

There is a field in the Subscription Portal element called "Authentication HMAC" this represents a secure code that must be generated in order for Billflow to authenticate users to access their subscription information.

In order to generate this, please select: **Insert Dynamic Data -> Get Data from an External API ->** Billflow **API - Generate HMAC's hmac**

The email should be the Current User's email, the secret can be found on the [integration page within Billflow](https://dashboard.billflow.io/integrations) (Note: Test mode secret is different from Live mode secret).

![](https://gblobscdn.gitbook.com/assets%2F-LkAdq4qKmsg1iQv3yZn%2F-M2dm4uuUhczPg2c_eXK%2F-M2tXdsyfKunq1y15yzS%2Fimage.png?alt=media\&token=59bf0b28-09c2-49ce-9920-7139b8c93a10)

## Subscription portal events and states

With this element, you can call workflows based on the following events, with the following states available within each:&#x20;

**Cancel Subscription Event** - Triggered when a user subscribes using the Pricing Embed

**Cancel Subscription States -**

* **current\_status -** The current status of the Stripe subscription

**Resubscribe Event** - Triggered when a user resubscribes

**Resubscribe States** -&#x20;

* **current\_subscription\_id** - The current ID of the Stripe subscription (resubscribe creates a new subscription if the subscription was completely canceled)
* **current\_status** - The status of the Stripe subscription

**Change Tier Event** - Triggered when a user changes their plan/tier

**Change Tier States -**

* **current\_tier** - The current tier that the user switched to


# How to connect Stripe webhooks to Bubble

## Description

When events happen outside of your app in Stripe, for example a customer's credit card failing, you may want to take action within your Bubble application. This can be accomplished by connecting Stripe webhooks to Bubble workflows so you can update your database whenever specific events occur within Stripe.&#x20;

## Video Guide

{% embed url="<https://www.youtube.com/watch?v=rY-RJrHze68>" %}

## Steps

### 1. Enable Workflow API in Bubble

In Bubble, go to your application's **Setting -> API** and check "This app exposes a Workflow API"

![](/files/-MJ4-FGpSX1hrIc6163v)

### 2. Create workflows in Bubble

#### a. Go to "Backend workflows"

Now that the Workflow API is enabled, under your pages you should see a new page at the bottom called "Backend workflows" - this is where you can define new workflows to be triggered by Stripe webhooks

![](/files/-MJ4-HjOSpnlP2dfJ6wJ)

#### b. Create a new workflow endpoint

Define a new Workflow, this will create an API endpoint that can be called by Stripe. Be sure to enable:

* Expose as a public endpoint
* This endpoint can be run without authentication
* Ignore privacy rules when running the workflow

You will be creating a separate workflow endpoint for each Stripe event you are trying to monitor in Bubble

{% hint style="warning" %}
The endpoint name should follow URL patterns, so only use lowercase letters and avoid spaces and other special characters
{% endhint %}

![](/files/-MJ4-KPLI6OmnUD1kHhr)

### 3. Create webhooks in Stripe and Detect data

{% hint style="info" %}
The webhook URL will be different depending on the version of the Bubble application, we recommend putting your test Bubble workflow endpoint URL in Stripe test mode and the live bubble URL in Stripe live mode
{% endhint %}

Next, we want to detect the data that Stripe is going to be sending, so click "Detect data" and copy the URL presented, then go to the Stripe webhook section (<https://dashboard.stripe.com/test/webhooks>)

Because the workflow we created in the previous step the goal is to monitor the subscription status, we have it send on update or delete of the subscription.&#x20;

After that paste the URL that appeared when you clicked "Detect Data"

![](/files/-MJ4-Nh-5wOh_YqGjMB1)

Next click "Send test webhook" and send an event to Bubble to detect the data. It should show as successful and your Bubble application should look like this&#x20;

![](/files/-MJ4-QVhHLu_Aq2db8W8)

After saving the request data in Bubble, modify the stripe webhook you just created to no longer have a "/initialize" at the end of it:

### 4. Configure Bubble Workflow to process Stripe webhooks

In this example we are assuming we have the Stripe subscription\_id and subscription\_status as fields on the User. We query users by the subscription\_id and modify the subscription\_status. This kind of flow can be adapted to any data model.

![](/files/-MJ4-TT3RyXKxp7Yo-Px)

After this is done you are ready to test the webhook

### 5. Test the Stripe integration

{% hint style="info" %}
Make sure you updated your Stripe webhook URL to not have the trailing /initialize that was used to detect the data type
{% endhint %}

Assuming you have a similar setup to the one above, you should have a User with a subscription in Stripe. To test, just cancel an active subscription and the user's subscription\_status should be updated to a canceled state.&#x20;

{% hint style="info" %}
When you define the Stripe webhook in Live mode Stripe (<https://dashboard.stripe.com/webhooks>) the URL will be different, the format it follows is:&#x20;

[https://{BUBBLE\_APP\_NAME}.bubbleapps.io/api/1.1/wf/{WORKFLOW-NAME}](https://{BUBBLE_APP_NAME}.bubbleapps.io/version-{VERSION-NAME}/api/1.1/wf/{WORKFLOW-NAME}) (remove version-test)
{% endhint %}


# Webflow

Webflow Integration Instructions

## Integration Instructions

### Step 1: Create a Billing Page

For detailed instructions, check out the billing page of your needs.&#x20;

{% content-ref url="/pages/-MGTi2INq5nRltmKIukm" %}
[Checkout Form](/billing-pages/checkout-form)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp-BCnyC2J3H4eYNDY" %}
[Pricing Page](/billing-pages/pricing-page)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTi5VCJ3Jlw2v-LgIc" %}
[Customer Portal](/billing-pages/customer-portal)
{% endcontent-ref %}

{% hint style="info" %}
If you are using the customer portal, make sure to enable "[Billflow Email Auth](/billing-pages/customer-portal#billflow-email-auth)" in the Authentication Settings
{% endhint %}

### Step 2: Copy HTML5 code snippet

![Chose HTML Code](/files/-MKfaxL_xCv9v9owRmb2)

![Copy Code](/files/-MKfb23B7as5KDHDy3Yy)

### Step 3: Add to Webflow

Use standard [Webflow Custom Code embed element](https://university.webflow.com/lesson/custom-code-embed) to add Billflow billing pages to your Webflow site.


# WordPress

WordPress Plugin Instructions

## Features

* Provides Billflow embeds as WordPress Widgets
  * Pricing Page
  * Signup Form
  * Subscription Management Portal
* Uses WordPress user authentication
* Creates users on signup using the widget
* Stripe Webhooks
  * Create WordPress users on Stripe customer created event

{% hint style="warning" %}
Does not integrate with "Ultimate Member Plugin" role system
{% endhint %}

## Supported Pages

* Plan Picker
* Checkout Form
* Customer Portal
* Pricing Page
* Invoice Portal

## Requirements

PHP 7.1 on the WordPress hosting.

## Installation

There are 2 primary ways that you can install the WordPress plugin.&#x20;

### **Method 1 - The plugin store**

Install via your WordPress site's admin panel under `http://your_wp_domain.com/wp-admin/plugin-install.php?s=servicebot&tab=search&type=term`

* Replace `your_wp_domain.com` with your actual domain
* Click install button
* Then click activate button

{% hint style="info" %}
If you see error saying "Cannot create directory" or "Permission error", this is because your server may not be setup properly, please try method 2 below.
{% endhint %}

### **Method 2 - Upload to your server**

Install by downloading the plugin from [here](http://wordpress.org/plugins/servicebot).

* Extract the downloaded Zip file
* Upload the Extracted folder to your sever under **`/wp-content/plugins/[upload extracted folder here]`** via FTP or other methods available in your hosting setup.
* Log into your WordPress site and go to **`/wp-admin/plugins.php`** and enable “Billflow"&#x20;

Then go to **`/wp-admin/admin.php?page=servicebot_plugins`** and [setup Billflow configuration.](https://docs.servicebot.io/subscription-portal/integrations/wordpress#step-1-configure-global-settings)

## Configuration

### Step 1: Configure Global Settings

Global settings apply to all widgets as the default settings unless overridden in the Widget settings.

#### Settings

| Field                     | Description                                                                                     |
| ------------------------- | ----------------------------------------------------------------------------------------------- |
| Secret Key                | Test mode secret key. Go [here to view](https://dashboard.servicebot.io/integrations/wordpress) |
| Create WP user on signup? | Check this box to create a WordPress user on signup from the widget.                            |

### Step 2: Optionally Configure Stripe Webhooks

#### Stripe Webhooks Settings

You can optionally use the Stripe Webhooks handler that comes with this plugin to create WordPress users when a Stripe Customer is created.&#x20;

> Another use case for this is when you are not signing up users with our WordPress Widgets, but users are signed up from another source, such as ClickFunnel pages. You can let those customers user your WordPress site for our customer portal embed to see their subscriptions.

First, you need to configure the Webhook handler in your Stripe dashboard. Go [here to configure](https://dashboard.stripe.com/webhooks).

{% hint style="info" %}
You will need to do this for both Live and Test mode.
{% endhint %}

1. Click on the `Add endpoint` button
2. Paste `https://your_wp_domain.com/billflow/v1/stripe-hooks` into the Endpoint URL input box &#x20;
3. Select one of the following create events
   1. `customer.created`- allow all of your Stripe customers to be able to have an account on your WordPress site to view their subscriptions.
   2. `customer.subscription.created` - allow only those Stripe customers who signed up for a service that matches your WordPress Billflow Plugin's service setting.
4. Click `Add endpoint` to save

{% hint style="info" %}
Please only use one of the create events and not both.&#x20;
{% endhint %}

![Configure the Webhook handler in Stripe ](/files/-MJ40tocf9x-DamhJ0NH)

### Other Supported Events

| Stripe Webhook Event          | Description                                                                                                                              |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| customer.subscription.updated | By enabling this event, our WP plugin will handle the event on user change plan, and update WP user roles if it was setup in the plugin. |
| customer.subscription.deleted | By enabling this event, our WP plugin will handle the event on user subscription cancelation, the WP user roles will be removed.         |

Then, you need to configure the WordPress plugin with the following keys:

| Fields                  | Description                                                                                                                                                                                                                                                                                             |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Stripe Test Secret Key  | Test Secret Key from your Stripe dashboard. Go [here to view](https://dashboard.stripe.com/test/apikeys)                                                                                                                                                                                                |
| Stripe Live Secret Key  | Live Secret Key from your Stripe dashboard. Go [here to view](https://dashboard.stripe.com/apikeys)                                                                                                                                                                                                     |
| Stripe Test Signing Key | <p>Test Signing Key to verify that the events were sent by Stripe. </p><p>Go<a href="https://dashboard.stripe.com/webhooks"> here and select</a> the Webhook you configured for this integration. </p><p><code>See how:</code> <img src="/files/-MJ41-kA4QurFlBGFJB5" alt="" data-size="original"> </p> |
| Stripe Live Signing Key | <p>Test Signing Key to verify that the events were sent by Stripe. </p><p>Go<a href="https://dashboard.stripe.com/webhooks"> here and select</a> the Webhook you configured for this integration. </p><p><code>See how:</code> <img src="/files/-MJ4121qW4QWWx9z-G2M" alt="" data-size="original"> </p> |
| Live Mode               | Check this box to listen to live mode Stripe webhooks                                                                                                                                                                                                                                                   |

Now, your Stripe Webhook handler should be working.&#x20;

You can verify by creating a customer in the Stripe dashboard then going to your WordPress site and checking if the user is created. (Webhooks may have a couple minute delay)

## Next: Add your Widget

Click next to see how to add your widget


# Add Widgets

## Billflow **Shortcode**

### Step 1: Create a page to hold the Billflow widget.

You can create any page using your normal WordPress editor or page builder to do this.

### Step 2: Use the shortcode to place a billing page widget

| Shortcode                                           | Editor Screenshot                                                   |
| --------------------------------------------------- | ------------------------------------------------------------------- |
| `[billflow billing_page_id="your_billing_page_id"]` | <img src="/files/-MJbt2qvQGhHiL76-4gd" alt="" data-size="original"> |

### Optional Step: override additional configurations via the Shortcode parameters.

The shortcode examples above default to use the settings that you set in the Billflow plugin settings page. However, some people have the use case to override the settings for individual pages, so we have the following setting available to override using the shortcodes.&#x20;

### Available shortcode parameters

| `billing_page_id` |                                                     |
| ----------------- | --------------------------------------------------- |
| Example Value     | "9c7ECmmhey47zZsmEtWC"                              |
| Value Type        | String                                              |
| Description       | Your billing page id from dashboard.billflow\.io    |
| Example           | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC"]` |

| `gated`                                          |                                                                                      |
| ------------------------------------------------ | ------------------------------------------------------------------------------------ |
| Example Value                                    | "subscriber" OR "subscriber, customer"                                               |
| Value Type                                       | String OR Array of strings                                                           |
| Description                                      | String for the allowed user role OR An array of allowed user roles                   |
| <p>Example:</p><p>With a single allowed role</p> | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC" gated="subscriber"]`               |
| <p>Example:</p><p>With a list of allowed </p>    | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC" gated="basic_user, premium_user"]` |

| `logged_out_only`                                   |                                                                                                                                                            |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Value                                               | true \| a redirect url relative                                                                                                                            |
| Description                                         | Makes the page a logged out only page, if a user is logged in, they will be sent to the home page if it is set to true. Or you can specify a redirect url. |
| <p>Example:<br>Redirect user to your home page</p>  | \[billflow billing\_page\_id="9c7ECmmhey47zZsmEtWC" logged\_out\_only="true"]                                                                              |
| <p>Example:<br>Redirect user to and custom page</p> | \[billflow billing\_page\_id="9c7ECmmhey47zZsmEtWC" logged\_out\_only="/my-portal-page"]                                                                   |

| `logged_in_only`                                           |                                                                                                                               |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Example Value                                              | "true" OR "/a-relative-url-to-the-domain"                                                                                     |
| Value Type                                                 | String                                                                                                                        |
| Description                                                | Makes the page a logged in only page, if a user is logged out, they will be sent to the login page or the redirect urlExample |
| <p>Example:</p><p>Redirect user to standard login page</p> | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC" loggin_in_only="true"]`                                                     |
| <p>Example:</p><p>Redirect user to a custom page</p>       | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC" loggin_in_only="/my-login-page"]`                                           |

| `upgrade`                                              |                                                                                                                                   |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| Example Value                                          | "/a-relative-url-to-your-domain"                                                                                                  |
| Value Type                                             | String                                                                                                                            |
| Description                                            | If the current user does not have the role specified by the `gated` parameter, it will send the user to this upgrade page.Example |
| <p>Example:</p><p>Redirect user to an upgrade page</p> | `[billflow billing_page_id="9c7ECmmhey47zZsmEtWC" gated="subscriber" upgrade="/upgrade-checkout-page"]`                           |

## Next: Advanced Usage

Click next to see how you can add custom frontend logics


# Advanced Usage

## APIs

### Add Custom Frontend logics

Implement this function allows you to implement frontend logics that will run after after subscription creation.&#x20;

#### How?

Define the following function in any of your js files, such as in your custom theme files, and implement any logic you’d like within the body.

```javascript
window.billflow_wp_handle_response = function myHandleResponseFunction({event, response, extras}){
	// your custom handling logic goes here
		console.log('called servicebot_wp_handle_response', response)
    console.log('event:' event)
}
```

| Param             | Description                                                                        |
| ----------------- | ---------------------------------------------------------------------------------- |
| event (string)    | 'create\_subscription'                                                             |
| response (object) | The Stripe [subscription object](https://stripe.com/docs/api/subscriptions/object) |
| extras (object)   | Contains extra information from the Billflow frontend                              |


# Useful Plugins

Useful plugins that often used when implementing Billflow on WordPress

## Restrict User Access

This plugin can help you gate some pages such as the Subscription Portal page to logged in WordPress users only. If someone is not logged in, you can redirect them to the login page.

You can also use this plugin to create custom WP roles, and use that along with our Plugin's Role => Sb\_Tier mapping.&#x20;

{% embed url="<https://wordpress.org/plugins/restrict-user-access/>" %}

## Members (by Memberpress)

This plugin can help you manage role and capabilities. Roles created with this plugin can be used with Billflow's subscription to roles mapping feature.

{% embed url="<https://wordpress.org/plugins/members/>" %}

## **WP Login Form**

This plugin can help you create a custom Login page

{% embed url="<https://wordpress.org/plugins/wp-login-form/>" %}

## **BNFW**

This plugin can help you customize emails that will be sent to your WordPress users

{% embed url="<https://wordpress.org/plugins/bnfw/>" %}

## **WP-Members**

{% hint style="info" %}
**The restrict user access plugin does not work on WordPress sites that are hosted on wordpress.com**
{% endhint %}

{% embed url="<https://wordpress.org/plugins/wp-members/>" %}

**Details on:** <http://wpcomstaging.com>

**Wordpress.com support:** <https://en.support.wordpress.com/domains/>


# Notion

Notion Integration Instructions

## Supported Pages

* Checkout Form
* Pricing Page

## Integration Instructions

### Step 1: Create a Billing Page

For detailed instructions, check out the billing page of your needs.&#x20;

{% content-ref url="/pages/-MGTi2INq5nRltmKIukm" %}
[Checkout Form](/billing-pages/checkout-form)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp-BCnyC2J3H4eYNDY" %}
[Pricing Page](/billing-pages/pricing-page)
{% endcontent-ref %}

### Step 2: Copy HTML5 code snippet

![Chose HTML](/files/-MKfaxL_xCv9v9owRmb2)

![Copy Code](/files/-MKfb23B7as5KDHDy3Yy)

### Step 3: Create Site in [HTML Save](http://htmlsave.com/)

HTML Save allows you to host code on a static site very easily.&#x20;

### Step 4: Copy and HTML Save Link

![Add Billflow Code snippet to HTML Save](/files/-MKfeHiMbaFT7JAKDqth)

![Copy your Site Link](/files/-MKfeOmMMG5PFupUzt7-)

### Step 5: Go to Notion Page and Embed

![Use /embed](/files/-MKfeUDFBGiZl0v17hgn)

![](/files/-MQn21oAlXY7LbPOk1s0)


# Drupal

Drupal Plugin Instructions

## Supported Pages

* Plan Picker
* Checkout Form
* Customer Portal
* Pricing Page
* Invoice Portal

## Features

* Provides Billflow embeds&#x20;
* Uses Drupal user authentication
* Creates users on signup using the widget
* Stripe Webhooks
  * Create Wordpress users on Stripe customer created event

{% embed url="<https://www.drupal.org/project/servicebot>" %}


# Rewardful

Rewardful Integration Details

Looking to set up an affiliate program for your business? You've come to the right place.

To make it easier & faster to start and grow a SaaS business on Stripe, Billflow & Rewardful have teamed up to offer the easiest and most powerful way to create an affiliate program. The most untapped sources of new customers are your existing customers, network and relevant pre-built audiences. There's a ton of noise in the market and prospects often aren't familiar with your brand. Luckily, buyers rely on word-of-mouth 2-10x more than paid media and 92% of consumers trust referrals from people they know.

## Features <a href="#features" id="features"></a>

* Generate affiliate signup links that give commissions to the referrer
* View Rewardful data directly from your Stripe dashboard. Billflow & Rewardful have the deepest integrations with Stripe you'll find
* Automatically adjust commissions for customer actions in Billflow like upgrades, downgrades, cancellations, and free trials
* No-code integration

## How it works <a href="#how-it-works" id="how-it-works"></a>

The Rewardful integration works completely out of the box. Add the Rewardful Javascript snippet to your site. Rewardful generates urls for affiliates, when people visit your website from one, Billflow pulls metadata from a cookie, adds it to metadata in Stripe, then Rewardful does its payouts and everything based on the data in Stripe.

Of the Rewardful Install steps, you only need to complete Step One. Billflow will automatically take care of the rest with our Checkout Form.

![](https://gblobscdn.gitbook.com/assets%2F-LkAdq4qKmsg1iQv3yZn%2F-M8RtnTNxnkX37f-cxPU%2F-M8S4Tjpa4zn9-oTwcWu%2FScreen%20Shot%202020-05-28%20at%204.55.22%20PM.png?alt=media\&token=2545fafe-5050-40fe-a1b2-1d79b0304ddf)


# ChurnKey

Churnkey Integration Details

Churnkey provides customizable churn flows to help you reduce churn and understand why users are leaving.&#x20;

Billflow now provides an easy to use integration with Churnkey. Bellow are the steps to get started.

## Enable on Billing page

Go to the Advanced settings of your customer portal and enable "Use Churnkey"

![](/files/-MjAVSIUHFm-92K1aW9B)

This will add configurations keys to your embed snippet so values can be dynamically set.

## Churnkey installation

You can find the Churnkey installation steps by logging into [Churnkey](https://app.churnkey.co/) and clicking on "Embed"

### Step 1

The Step 1 on Churnkey's installation instructions can be skipped, Billflow takes care of that for you.

### Step 2

You need to generate a security hash for Churnkey the same way it is done for billflow, by running a piece of serverside code with your logged-in customer's Stripe ID and a secret key.

### Step 3

Step 3 in Churnkey's instructions is where you can grab your appId. You will notice these are the same keys that get generated on your Billflow snippet.

You will see the following configurations added to your Billflow embed snippet.

```
plugins: {
				churnkey: {
								appId: "",								
								customer_id: "",
								authHash: "",
								mode: "",
				}
}
```

| Key          | Value                                                                                                                                                                                                    |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| appId        | Churnkey App ID. Grab this from Step 3 of the Churnkey Embed instructions.                                                                                                                               |
| customer\_id | Set to the Stripe customer ID of the logged in user. Eg: cus\_K9c72057lXagII                                                                                                                             |
| authHash     | Set to the authentication hash generated with your Churnkey server-side snippet. This is different that the Billflow hash although the generation steps are very similar.                                |
| mode         | Set to the Stripe mode you want to be in. Both the Billflow modes and the Churnkey modes map to Stripe Test and Live mode. Normally set this to the same mode as your billing page. Eg: "test" or "live" |


# Embed Configurations

Billing page options are set from the Billflow dashboard, or passed in through the embed snippet. It's necessary to pass some options through that are dynamic by nature, like the user's email or security hash. Passing in an option will override the option set from the dashboard. Following are the options available for each billing page.

{% hint style="info" %}
If you are using any of the billing pages that utilize another billing page (eg. Plan Picker uses Checkout Form when a customer selects a plan), you can add configuration options to the billing page for both. So make sure to check out Checkout Form Configs if you're using another billing page.
{% endhint %}

{% content-ref url="/pages/-MGTMCd5qX--QyvB6oPq" %}
[Plan Picker Configs](/developers/embed-configurations/plan-picker)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTNJkVGxhfZIRfLU28" %}
[Checkout Form Configs](/developers/embed-configurations/checkout)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTNMLZ3yymbmVUlSfQ" %}
[Customer Portal Configs](/developers/embed-configurations/customer-portal)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp0ZqMUfdu3fnXj1oq" %}
[Pricing Page Configs](/developers/embed-configurations/pricing-page)
{% endcontent-ref %}

{% content-ref url="/pages/-MGp0ajyBJmFGVZ9VFag" %}
[Invoice Portal Configs](/developers/embed-configurations/invoice-portal)
{% endcontent-ref %}


# Plan Picker Configs

Plan Picker Configuration Options

## Required Configs

### email

| Type   | Required            | Description                                                                                                                                              |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR customer\_id | The customer's email address. This will automatically populate checkout, or be used to identify current subscribers. Can alternatively use customer\_id. |

```javascript
{
    email: "example@google.com"
}
```

### customer\_id

| Type   | Required     | Description                                                                                                                                                                             |
| ------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR email | The customer's Stripe Customer ID. This will be used to identify existing subscribers or subscribe new customers. You must have already created the Stripe Customer object to use this. |

```javascript
{
        customer_id: "cus_FtWXI6U0YxebLd"
}
```

### hash

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                      |
| ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes      | An HMAC string used for authenticating the user loading the embed more securely. This is **required in order to go to 'Live Mode'** in Billflow (connected to 'Live Mode' in Stripe). The hash is generated with your Billflow Secret and the customer's email or Stripe Customer ID, whichever you are using to identify users. |

```javascript
{
    hash: "0709c7f107ed6326aaeaa3810330834870591f3924943e7bce66a826ac532045"
}
```

## Available Configs

### subscription\_id

| Type   | Required | Description                                                                                                                                                                              |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | No       | The Stripe subscription ID. Pass if you want a user to only see and manage a single subscription. Used if your customers have multiple subscriptions and you only want them to view one. |

```javascript
{
    subscription_id: "sub_I9cJJypSQHOfzl"
}
```

### service

| Type   | Required | Description                                                                                  |
| ------ | -------- | -------------------------------------------------------------------------------------------- |
| String | No       | The Billflow service. Use this to dynamically pass in different service to the billing page. |

```javascript
{
    service: "Your Service"
}
```

### handleResponse

| Type     | Required | Description                                                                                                                                                                                                                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Function | No       | Function that is called when users signup, change plan (upgrade/downgrade), resubscribe, or update Credit Card. Used to update user data, do redirects, or provide notifications. Payload contains an event name and a response object. [Learn More](/developers/handling-embed-events). |

```javascript
{
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
    }
}
```

### options.**disableTiers**

| Type  | Required | Description                                                                                                                                                                                                                                            |
| ----- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Array | No       | <p>Use to dynamically disable certain tiers for a customer when selecting a plan. Add an array of tiers (corresponds to metadata tag sb\_tier) to disable users from being able to change to those specific plans.</p><p>Eg: \['Tier 1', 'Tier 2']</p> |

```javascript
{
  options: {
      disableTiers: ['Tier 1', 'Tier 2']
  }
}
```

### options.quantity

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | <p>Use to set the quantity of a subscription during creation. Can pass in an integer or an object of key-value pairs. The unit\_label is defined on the Stripe product and used to define which quantity is being set. If an integer is passed, it will apply the quantity to all products on the tier, if an object is passed with the unit\_labels as keys, it will assign that quantity to the respective unit\_label.</p><p>Eg: 5</p><p>OR</p><p>Eg: {product\_unit\_label1 : 10, unit\_label2: 20}</p> |

```javascript
{
  options: {
      quantity: {
        super_user: 3,
        user: 5,
      },
  }
}
```


# Checkout Form Configs

Checkout Form Configuration Options

## Required Configs

### email

| Type   | Required            | Description                                                                                                                                              |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR customer\_id | The customer's email address. This will automatically populate checkout, or be used to identify current subscribers. Can alternatively use customer\_id. |

```javascript
{
    email: "example@google.com"
}
```

### customer\_id

| Type   | Required     | Description                                                                                                                                                                             |
| ------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR email | The customer's Stripe Customer ID. This will be used to identify existing subscribers or subscribe new customers. You must have already created the Stripe Customer object to use this. |

```javascript
{
        customer_id: "cus_FtWXI6U0YxebLd"
}
```

### hash

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                  |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes      | An HMAC string used for authenticating the user loading the embed more securely. This is **required in order to go to 'Live Mode'** in Billflow (connected to 'Live Mode' in Stripe). The hash is generated with your Billflow ID and the customer's email or Stripe Customer ID, whichever you are using to identify users. |

```javascript
{
    hash: "0709c7f107ed6326aaeaa3810330834870591f3924943e7bce66a826ac532045"
}
```

## Available Configs

### them&#x65;**.stripeElement**

| Type   | Required | Description                                                                                                                                                |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | Add custom Stripe Element Styles. Inside the stripeElement object, it is exactly the same as how [Stripe works](https://stripe.com/docs/js/appendix/style) |

```javascript
{
   "billing_page_id":"YOUR_BILLING_PAGE_ID",
   ...
   ...
   "theme":{
      "stripeElement":{
         "style":{
            "base":{
               "fontSize":"14px",
               "lineHeight":"40px",
               "color":"white",
               "fontFamily":"-apple-system",
               "borderRadius":"4px",
               "::placeholder":{
                  "color":"white"
               }
            }
         }
      }
   }
}
```

### handleResponse

| Type     | Required | Description                                                                                                                                                                                                                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Function | No       | Function that is called when users signup, change plan (upgrade/downgrade), resubscribe, or update Credit Card. Used to update user data, do redirects, or provide notifications. Payload contains an event name and a response object. [Learn More](/developers/handling-embed-events). |

```javascript
{
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
    }
}
```

### coupon

| Type   | Required | Description                                                                                                                         |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| String | No       | Stripe coupon **ID**. Pass in to have a coupon automatically applied to all prices on the page. Also works with Stripe Promo Codes. |

```javascript
{
    coupon: "coupon_id"
}
```

### service

| Type   | Required | Description                                                                                  |
| ------ | -------- | -------------------------------------------------------------------------------------------- |
| String | No       | The Billflow service. Use this to dynamically pass in different service to the billing page. |

```javascript
{
    service: "Your Service"
}
```

### tier

| Type   | Required | Description                                                                                                             |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| String | No       | Tier name as defined by the sb\_tier metadata tag. Pass in tier & interval to dynamically show specific checkout forms. |

```javascript
{
    tier: "Basic"
}
```

### interval

| Type   | Required | Description                                                |
| ------ | -------- | ---------------------------------------------------------- |
| String | No       | Interval string for the desired tier. Eg: day, month, year |

```javascript
{
    interval: "month"
}
```

### interval\_count

| Type    | Required | Description                                                                                                                                       |
| ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Integer | No       | This is only required if you are using a custom interval like 'every 6 months' or 'every 2 weeks'. It will be the number for the custom interval. |

```javascript
{
    interval_count: 6
}
```

## Options

### option&#x73;**.metadata**

| Type   | Required | Description                                                                                                                        |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | An object of key-value pairs. They will be added to the metadata of the Customer and Subscription in Stripe when they are created. |

```javascript
{
    options: {
        metadata: {
            key1: "Value 1",
            key2: "Value 2"
        }
    }
}
```

### option&#x73;**.default\_tax\_rates**

| Type  | Required | Description                                                                                                                                                                                                                                                                                                                                               |
| ----- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Array | No       | An array of Stripe [tax rate IDs](https://stripe.com/docs/api/subscriptions/create#create_subscription-default_tax_rates) to be applied to a subscription on creation. You can learn more about Stripe tax rates [here](https://stripe.com/docs/billing/subscriptions/taxes#static-configuration). The tax rate will be applied on subscription creation. |

```javascript
{
    options: {
        default_tax_rates: [
            "txr_1HZfxhEGJvDU3rtbcukgdicw"
        ]
    }
}
```

### options.quantity

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | <p>Use to set the quantity of a subscription during creation. Can pass in an integer or an object of key-value pairs. The unit\_label is defined on the Stripe product and used to define which quantity is being set. If an integer is passed, it will apply the quantity to all products on the tier, if an object is passed with the unit\_labels as keys, it will assign that quantity to the respective unit\_label.</p><p>Eg: 5</p><p>OR</p><p>Eg: {product\_unit\_label1 : 10, unit\_label2: 20}</p> |

```javascript
{
  options: {
      quantity: {
        super_user: 3,
        user: 5,
      },
  }
}
```


# Customer Portal Configs

Customer Portal Configuration Options

## Required Configs

### email

| Type   | Required            | Description                                                                                                                                              |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR customer\_id | The customer's email address. This will automatically populate checkout, or be used to identify current subscribers. Can alternatively use customer\_id. |

```javascript
{
    email: "example@google.com"
}
```

### customer\_id

| Type   | Required     | Description                                                                                                                                                                             |
| ------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR email | The customer's Stripe Customer ID. This will be used to identify existing subscribers or subscribe new customers. You must have already created the Stripe Customer object to use this. |

```javascript
{
        customer_id: "cus_FtWXI6U0YxebLd"
}
```

### hash

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                      |
| ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes      | An HMAC string used for authenticating the user loading the embed more securely. This is **required in order to go to 'Live Mode'** in Billflow (connected to 'Live Mode' in Stripe). The hash is generated with your Billflow Secret and the customer's email or Stripe Customer ID, whichever you are using to identify users. |

```javascript
{
    hash: "0709c7f107ed6326aaeaa3810330834870591f3924943e7bce66a826ac532045"
}
```

## Available Configs

### subscription\_id

| Type   | Required | Description                                                                                                                                                                              |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | No       | The Stripe subscription ID. Pass if you want a user to only see and manage a single subscription. Used if your customers have multiple subscriptions and you only want them to view one. |

```javascript
{
    subscription_id: "sub_I9cJJypSQHOfzl"
}
```

### service

| Type   | Required | Description                                                                                  |
| ------ | -------- | -------------------------------------------------------------------------------------------- |
| String | No       | The Billflow service. Use this to dynamically pass in different service to the billing page. |

```javascript
{
    service: "Your Service"
}
```

### handleResponse

| Type     | Required | Description                                                                                                                                                                                                                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Function | No       | Function that is called when users signup, change plan (upgrade/downgrade), resubscribe, or update Credit Card. Used to update user data, do redirects, or provide notifications. Payload contains an event name and a response object. [Learn More](/developers/handling-embed-events). |

```javascript
{
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
    }
}
```

### options.quantity

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | <p>Use to set the quantity of a subscription during creation. Can pass in an integer or an object of key-value pairs. The unit\_label is defined on the Stripe product and used to define which quantity is being set. If an integer is passed, it will apply the quantity to all products on the tier, if an object is passed with the unit\_labels as keys, it will assign that quantity to the respective unit\_label.</p><p>Eg: 5</p><p>OR</p><p>Eg: {product\_unit\_label1 : 10, unit\_label2: 20}</p> |

```javascript
{
  options: {
      quantity: {
        super_user: 3,
        user: 5,
      },
  }
}
```


# Pricing Page Configs

Pricing Page Configuration Options

## Available Configs

### email

| Type   | Required | Description                                                                                            |
| ------ | -------- | ------------------------------------------------------------------------------------------------------ |
| String | No       | The customer's email address. Pass this in so customers do not need to enter in their email on signup. |

```javascript
{
    email: "example@google.com"
}
```

### service

| Type   | Required | Description                                                                                  |
| ------ | -------- | -------------------------------------------------------------------------------------------- |
| String | No       | The Billflow service. Use this to dynamically pass in different service to the billing page. |

```javascript
{
    service: "Your Service"
}
```

### customer\_id

| Type   | Required | Description                                                                                                                                             |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | No       | The customer's Stripe Customer ID. Pass this in to checkout an existing customer. You must have already created the Stripe Customer object to use this. |

```javascript
{
        customer_id: "cus_FtWXI6U0YxebLd"
}
```

### handleResponse

| Type     | Required | Description                                                                                                                                                                                                                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Function | No       | Function that is called when users signup, change plan (upgrade/downgrade), resubscribe, or update Credit Card. Used to update user data, do redirects, or provide notifications. Payload contains an event name and a response object. [Learn More](/developers/handling-embed-events). |

```javascript
{
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
    }
}
```

### options.**disableTiers**

| Type  | Required | Description                                                                                                                                                                                                                                            |
| ----- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Array | No       | <p>Use to dynamically disable certain tiers for a customer when selecting a plan. Add an array of tiers (corresponds to metadata tag sb\_tier) to disable users from being able to change to those specific plans.</p><p>Eg: \['Tier 1', 'Tier 2']</p> |

```javascript
{
  options: {
      disableTiers: ['Tier 1', 'Tier 2']
  }
}
```

### options.quantity

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Object | No       | <p>Use to set the quantity of a subscription during creation. Can pass in an integer or an object of key-value pairs. The unit\_label is defined on the Stripe product and used to define which quantity is being set. If an integer is passed, it will apply the quantity to all products on the tier, if an object is passed with the unit\_labels as keys, it will assign that quantity to the respective unit\_label.</p><p>Eg: 5</p><p>OR</p><p>Eg: {product\_unit\_label1 : 10, unit\_label2: 20}</p> |

```javascript
{
  options: {
      quantity: {
        super_user: 3,
        user: 5,
      },
  }
}
```


# Invoice Portal Configs

Invoice Portal Configuration Options

## Required Configs

### email

| Type   | Required            | Description                                                                                                                                              |
| ------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR customer\_id | The customer's email address. This will automatically populate checkout, or be used to identify current subscribers. Can alternatively use customer\_id. |

```javascript
{
    email: "example@google.com"
}
```

### customer\_id

| Type   | Required     | Description                                                                                                                                                                             |
| ------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes OR email | The customer's Stripe Customer ID. This will be used to identify existing subscribers or subscribe new customers. You must have already created the Stripe Customer object to use this. |

```javascript
{
        customer_id: "cus_FtWXI6U0YxebLd"
}
```

### hash

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                      |
| ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | Yes      | An HMAC string used for authenticating the user loading the embed more securely. This is **required in order to go to 'Live Mode'** in Billflow (connected to 'Live Mode' in Stripe). The hash is generated with your Billflow Secret and the customer's email or Stripe Customer ID, whichever you are using to identify users. |

```javascript
{
    hash: "0709c7f107ed6326aaeaa3810330834870591f3924943e7bce66a826ac532045"
}
```

## Available Configs

### subscription\_id

| Type   | Required | Description                                                                                                                                                                              |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String | No       | The Stripe subscription ID. Pass if you want a user to only see and manage a single subscription. Used if your customers have multiple subscriptions and you only want them to view one. |

```javascript
{
    subscription_id: "sub_I9cJJypSQHOfzl"
}
```

### handleResponse

| Type     | Required | Description                                                                                                                                                                                                                                                                              |
| -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Function | No       | Function that is called when users signup, change plan (upgrade/downgrade), resubscribe, or update Credit Card. Used to update user data, do redirects, or provide notifications. Payload contains an event name and a response object. [Learn More](/developers/handling-embed-events). |

```javascript
{
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
    }
}
```

### options.quantity

| Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Object | No       | <p>Use to set the quantity of a subscription during creation. Can get an integer or an object of key-value pairs. The quantity will apply to products with the unit\_label defined. If an integer is passed, it will apply the quantity to all products on the tier, if an object is passed with the unit\_labels as keys, it will assign that quantity to the respective unit\_label.</p><p>Eg: 5</p><p>OR</p><p>Eg: {product\_unit\_label1 : 10, unit\_label2: 20}</p> |

```javascript
{
  options: {
      quantity: {
        super_user: 3,
        user: 5,
      },
}
```


# Handling Events

Handling actions & events in a billing page

## Handling actions <a href="#handling-actions" id="handling-actions"></a>

The handleResponse function can be used to update user information in your database regarding the customers subscription information, to do redirects on signup, or present notifications.

### Parameters <a href="#parameters" id="parameters"></a>

handleResponse will pass a variable which contains the following properties

| Variable Name | Description                              |
| ------------- | ---------------------------------------- |
| **event**     | The name of the event that occurred      |
| **response**  | The response object returned from Stripe |

### Events <a href="#events" id="events"></a>

| Event Name                | Description                                                                                                                                                                                                                                                                                          | Response Object                                                                                                                     |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| **pre\_load**             | First thing run after the embed javascript loads, before any API calls have been made. Use to inject React components or tell when the embed has loaded.                                                                                                                                             | Embed Configuration                                                                                                                 |
| **post\_load**            | <p>billingData: null — means the subscription portal is not loaded yet</p><p>billingData: {no\_user: true} — means the current email is not a customer</p><p>productData: null — means pricing (products) are not loaded yet</p><p>productData: \[ … ] — means the pricing (products) are loaded</p> | <p>billingData</p><p>currentConfig</p><p>productData</p>                                                                            |
| **pre\_subscribe**        | <p>This event allows you to do some actions before creating a subscription. For example, you can use it for checking if a user exists in your system.</p><p>Throwing an error here will prevent Billflow from creating a subscription. </p>                                                          | <p>email</p><p>service</p><p>tier</p>                                                                                               |
| **create\_subscription**  | Triggered when a subscription is created from a billing page. Use this event to update your user system with the Stripe subscription ID and tier. Learn more on the install guide.                                                                                                                   | ​[Subscription](https://stripe.com/docs/api/subscriptions/object)​                                                                  |
| **pre\_change\_plan**     | Triggered before when a user clicks on the confirm button, but before the API call is made to change plan.                                                                                                                                                                                           | <p>email</p><p>service</p><p>tier</p>                                                                                               |
| **change\_plan**          | Triggered when a user upgrades or downgrades using the Plan Picker. You can use this to update their tier information or create notifications.                                                                                                                                                       | ​[Subscription](https://stripe.com/docs/api/subscriptions/object)​                                                                  |
| **select\_plan**          | Triggered when a user selects a plan from the pricing page or plan picker. Use this to redirect to other pages or forms to create custom on-boarding flows.                                                                                                                                          | Tier name & [Plan](https://stripe.com/docs/api/plans/object)​                                                                       |
| **pre\_resubscribe**      | Triggered when a customer clicks on the resubscribe button, but before the API call is made to resubscribe.                                                                                                                                                                                          | <p>email</p><p>service</p><p>subscription\_id</p><p><a href="https://stripe.com/docs/api/subscriptions/object">Subscription</a></p> |
| **resubscribe**           | Triggered when a customer resubscribes from the portal. This occurs when a customer was cancelled, they come back to the portal and choose to resubscribe to a plan. Use this event to update your user system with the Stripe subscription ID and tier.                                             | ​[Subscription](https://stripe.com/docs/api/subscriptions/object)​                                                                  |
| **pre\_cancel**           | Triggered when a customer clicks on the cancellation button. Use this to create a custom cancellation flow.                                                                                                                                                                                          |                                                                                                                                     |
| **cancel\_subscription**  | Triggered when a customer requests a cancellation. Use this event to update subscription status for a user.                                                                                                                                                                                          | ​[Subscription](https://stripe.com/docs/api/subscriptions/object)​                                                                  |
| **pre\_change\_card**     | Triggered when a customer clicks on change card button, but before the API call is made to change card.                                                                                                                                                                                              | <p>email</p><p>service</p><p>subscription\_id</p><p><a href="https://stripe.com/docs/api/subscriptions/object">Subscription</a></p> |
| **update\_card**          | Triggered when a customer updates their Credit Card information or enters it for the first time. Use for presenting notifications to the user.                                                                                                                                                       | ​[Customer](https://stripe.com/docs/api/customers/object)​                                                                          |
| **request\_error**        | Triggered when any of our API requests failed. User for custom handling of any request failures.                                                                                                                                                                                                     | The Request Error                                                                                                                   |
| **pre\_update\_quantity** | Triggered before quantity is updated on a subscription from the customer portal                                                                                                                                                                                                                      | <p>Price</p><p>quantity</p><p>subscription\_id</p>                                                                                  |
| **update\_quantity**      | Triggered after a quantity has been updated from the customer portal                                                                                                                                                                                                                                 | [Subscription](https://stripe.com/docs/api/subscriptions/object)                                                                    |
| **add\_coupon**           | Triggered after a coupon has been added. Can be used to create custom coupon restriction logic.                                                                                                                                                                                                      | [Coupon](https://stripe.com/docs/api/coupons/object)                                                                                |

## Sample Redirect on Subscribe <a href="#sample-portal-code" id="sample-portal-code"></a>

Redirect to a URL after subscription

```markup
<div id="billflow-embed"></div>
<script>
  window.billflowSettings = {
    billing_page_id: "B4bD7TzIKxnsZfcgJoFk",
    email: "example@somemail.com",
    handleResponse: async function(payload) {
      console.log("Event ", payload.event);
      console.log("Response Object ", payload.response);
      //Redirect on Signup example
      if (payload.event == "create_subscription") {
        window.location.href = "https://google.com";
      }
    }
  };
  (function() {
    var s = document.createElement('script');
    s.src = 'https://js.billflow.io/billflow-embed.js';
    s.async = true;
    s.type = 'text/javascript';
    var x = document.getElementsByTagName('script')[0];
    x.parentNode.insertBefore(s, x);
  })();
</script>
```

## Sample Redirect based on Tier Subscribed

{% embed url="<https://codepen.io/kmidkiff/pen/XWjxqXp>" %}

## Sample Pricing Page redirect for specific tier <a href="#sample-portal-code" id="sample-portal-code"></a>

Redirect to a URL after subscription

```markup
<div id="billflow-embed"></div>
<script>
  window.billflowSettings = {
    "billing_page_id": "B4bD7TzIKxnsZfcgJoFk",
    "loader": "2",
    handleResponse: async function(payload) {
      let event = payload.event;
      let response = payload.response;
      //Redirect for free plan (update tiername check to yours)
      if (event == "select_plan") {
        let tierName = response.tier.tierName;
        if (tierName == "Starter") {
          window.location.href = "https://google.com"; //CHANGE ME
        }
      }
    }
  };
  (function() {
    var s = document.createElement('script');
    s.src = 'https://js.billflow.io/billflow-embed.js';
    s.async = true;
    s.type = 'text/javascript';
    var x = document.getElementsByTagName('script')[0];
    x.parentNode.insertBefore(s, x);
  })();
</script>
```

## Sample Existing User check

Skip subscription creation if a user already exists

```javascript
window.billflowSettings = {
	handleResponse: async function(payload) {
		// Implement pre subscribe hook example
    let { event, response } = payload;
		if (event === 'pre_subscribe') {
			// implement your logic for checking user exist in your system
			let { email, service, tier } = response;
			let exists = true;
			// throw an error for billflow to stop the subscribe action.
			if (exists) {
				throw {
					// displays an error message in servicebot
					message: 'User already exist, please login.',
					callback: () => {
						// call back to redirect or other actions you want to take.
						window.location = '/login';
					}
				};
			}
		}
	}
}
```

## Sample Track conversions with Google Analytics

Use GA to track signups

```javascript
window.billflowSettings = {
  handleResponse: async function (payload) {
    let { event, response } = payload;
    console.log("Event ", event);
    console.log("Response Object ", response); //Send record to google
    if (payload.event == "create_subscription") {
      let { email, seravice, tier } = response;
      var eventData = {
        event: "subscriptionPurchased",
        email: email
      };
      window.dataLayer.push(eventData);
    }
  }
};
```

## Sample Coupon restriction logic

Use to prevent a specific coupon based on logic

```javascript
  window.billflowSettings = {
    "billing_page_id": "MsPV2xxqNmPUjJVOEnu8",
    "handleResponse": function handleResponse(response) {
      // your code here 
      console.log("response", response)
      if (response.event === "add_coupon") {
        const coupon_id = response.response.coupon.id
        const bad_coupon = 'BAD'
        if (coupon_id == bad_coupon) {
          throw ({
            response: {
              data: {
                custom_error: "Custom Coupon Error~"
              }
            }
          })
        }
      }
    }
  };
```


# Languages & Frameworks

Samples of Billflow integrated

## Front End

Billflow provides an HTML/Javascript snippet that can be embedded on any frontend framework. Below you will find examples of Billflow embedded in some popular frontend frameworks. More coming soon!

The following functions are exposed by the Billflow js.

| Function          | Usage                                                                              |
| ----------------- | ---------------------------------------------------------------------------------- |
| init(settings)    | call this when your user enters the page with billflow embedded                    |
| destroy()         | call this when your user leaves the page with billflow embedded                    |
| refresh(settings) | call this if your application updates some settings while user remains on the page |

### Angular

{% embed url="<https://github.com/IOMechs/angular-service-bot>" %}

### React

[NPM package](https://github.com/service-bot/billflow-react) is available for React.&#x20;

{% hint style="info" %}
Seeing React errors? It could be because of loading the Billflow js multiple times. To prevent Billflow from automatically starting, pass`initialize: "no"` to the config
{% endhint %}

#### Hook: useBillflowEmbed

{% embed url="<https://codesandbox.io/embed/billflow-react-npm-example-zl4w3?fontsize=14&hidenavigation=1&theme=dark&view=editor>" %}

#### Functional

{% embed url="<https://gist.github.com/lsydev/3c3ec9730599a1c6c51911192bb2f6b6>" %}

### Vue

{% embed url="<https://codepen.io/kslung/pen/QWpzxLN>" %}

## Full Stack

Below are samples of full stack integrations with Billflow including user creation, security hash (HMAC), user auth, and webhooks. More coming soon!

### Node.js Sample Integration

This is a sample of a Billflow integration with the most popular Node.js Boilerplate on Github. It includes:

* User Signup & Authentication
* Customer & Subscription creation with the Subscription Management Portal
* User data updates with handleResponse
* User data updates with webhooks

{% embed url="<https://github.com/service-bot/hackathon-starter-servicebot-embed>" %}

##


# Customize Elements

Billflow Configuration API for customizing Billflow UI elements

Custom elements are possible starting in Billflow v4 beta. This page describes what is available for customization and how it works with examples.

## Customizable UI elements

If the out of the box UI elements or text does not fully fit what you need, we've got you covered. This is the list of customizable UIs within the Billflow embeds.

### Embed Elements

* [Loader](/developers/custom-elements#embed-loader)

### Pricing Table

This customization will apply to the pricing page, plan picker and portal embed's change plan view.

* Pricing tiers
  * [Pricing items](/developers/custom-elements#pricing-pricing-items)
  * [Select plan button](/developers/custom-elements#pricing-select-plan-button)

### Checkout

This customization will apply to the pricing page's checkout modal and the checkout page embed.

* Checkout items
  * [Price description](/developers/custom-elements#checkout-price-item-description)
  * [Price](/developers/custom-elements#checkout-price-item-price)

## The API

### Configuration Structure

This is how you would create the structure and pass it into the Billflow configuration in the embed code. For each customElement mentioned, refer to the [Custom element API](/developers/custom-elements#custom-element-api) section.

```javascript
/**
* You would pass this custom elements object into billflowSettings
* with your embed code like the code fragment below.
*
* windows.billflowSettings = {
*    billing_page_id: 'xxxxxxxxxxxxxx',
*    options: {
*        customElements,
*    }
*/

const customElements = {
    elements: {
        pricing: { // define all customizable elements within the pricing table view here
            tiers: [
                {
                    name: "Basic", // your tier name to be customized
                    highlighted: {
                        element: customHighlightedBasic // your custom element for this tier's highlight
                    },
                    select: {
                        element: customSelectBasic // your custom element for select button for this tier.
                    },
                    prices: [
                        {
                            id: "price_1jw91203djejd23", // your Stripe price id displayed in this tier.
                            element: customPrice // your custom element for price item in the table.
                        }
                    ]
                }
            ]
        },
        checkout: { // define all customizable elements within the checkout view here
            prices: [
                {
                    id: "price_1jw91203djejd23", // your Stripe price id displayed in this checkout form.
                    description: {
                        element: customDescription, // your custom element for this price description
                    },
                    price: {
                        element: customPriceDisplay, // your custom element for this price display
                    }
                }
            ]
        }
    }
}
```

### Custom element API

The interface to this custom element api is the same for each element level as follows:

```javascript
{
    type: "div", // Required, the element wrapping element type.
    props: {}, // Optional, the props you'd like to pass to the wrapping element, such as className.
    render: (props) => { // Optional instead of children, allows you to return HTML with dynamic values.
        // prop are based on the current element being customized, 
        // data properties would be for example, the Stripe price
        // object if customzing a price item.
        console.log("Log the props to see what's available to you", props)
        const { unit_amount } = props 
        return `<div>${unit_amount} per month</div>`
    },
    children: "Static Text" // Optional instead of render, if you simply want to customize it with static text.
}
```

## Examples

There are times when you want to customize the pricing information in the pricing table or even add extra elements to it. We will show you how to do it with the following examples.

### Embed: Loader

{% embed url="<https://codepen.io/kslung/pen/oNWaxXW?editors=0010>" %}
Displaying the custom loader instead of our standard spinning circle
{% endembed %}

### Pricing: Pricing Items

This section describes how you can customize the **Pricing Items** like the following example.&#x20;

{% embed url="<https://codepen.io/kslung/pen/wvdPyWj>" %}
Customized Basic Tier (Left) Price Item Example
{% endembed %}

To customize a pricing item, you will first create a custom pricing item element like this.

```javascript
/** Create the custom pricing item */
const CustomBasicPrice = {
  id: "price_HDa0zWHKXsY2sb", // replace with your own Stripe price id
  element: {
    type: "div",
    render: (props) => {
      // props is the price object in this case
      const { currency, unit_amount, priceRenderer } = props;
      const price = priceRenderer({amount: unit_amount ,currency})
      return `<div>
          ${price} <span>/ mo.</span>
          <i>Send up to 100,000 emails/mo before overages apply.</i>
        </div>`;
    }
  }
}
```

The `id` specifies the Stripe price item to customize within the tier.

The `element` is the custom element you will create. &#x20;

| Element properties |          |          |                                                                                                                                                                                                                                              |
| ------------------ | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type               | Required | string   | a valid html type                                                                                                                                                                                                                            |
| props              | Optional | object   | any valid props for the html element, such as class, id, etc.                                                                                                                                                                                |
| render             | Required | function | <p>a render function that will return the custom content as a string, basic html tags are will work.</p><p></p><p>Stripe price object is passed to this function from Billflow, you can use the values to create the custom element.    </p> |

Then you can pass the `CustomBasicPrice` to the config options.

```javascript
/** Add the custom pricing item element
 to Billflow Config options like this. */
{
  billing_page_id: "5GNX3vmderQxoquHKUPe",
  options: {
    elements: {
      pricing: {
        tiers: [
          {
            name: "Basic",
            prices: [ CustomBasicPrice ]
          }
        ]
      }
    }
  }
}
```

[Checkout the full example code here.](https://codepen.io/kslung/pen/wvdPyWj)

### Pricing: Select Plan Button

This section describes how you can customize the **Select Plan Button** like the following example.

{% embed url="<https://codepen.io/kslung/pen/poPdaqz?editors=0010>" %}
Customize the custom tier's Select Plan Button to open your Intercom chat
{% endembed %}

To customize a Select Plan Button, you will first create a custom element like this.

```javascript
/** Create the custom Enterprise tier button */
const CustomEnterpriseButton = {
    element: {
      type: "button", // element type
      props: { // any valid props that Reactjs accepts
        onClick: (e) => {
          e.preventDefault();
          alert("Trigger a custom action, such as open intercom.")
        },
        id: "custom-button",
        className:
          "custom-button sc-csTbgd kglWtV bf-button __full _3NM6Cu2g7QjO6j4WSEYBGp _1RTkeWIbayZ7rSk_0XZ-hN",
        href: "#"
      },
      children: "Contact Us" // the child element to be rendered in the custom element.
    }
  }

```

Then you can pass the `CustomEnterpriseTier` to the config options.

```javascript
/** Add the custom Enterprise tier button element
 to Billflow Config options like this. */
{
  billing_page_id: "5GNX3vmderQxoquHKUPe",
  options: {
    elements: {
      pricing: {
        tiers: [
          {
            name: "Enterprise", // the sb_tier name you want to customize
            select: CustomEnterpriseButton // customizing the select button for the Custom tier
          }
        ]
      }
    }
  }
}
```

[Checkout the full example code here.](https://codepen.io/kslung/pen/poPdaqz)

### Checkout: Price Item description

This section describes how you can customize the **Price Description** within the checkout view like the following example.

{% embed url="<https://codepen.io/kslung/pen/KKmozzy?editors=1100>" %}
Customized checkout price description highlighted in red
{% endembed %}

To customize a price description, you will first create a custom element like this.

```javascript
const CustomPriceDescription = {
  "id": "price_HDa0zWHKXsY2sb",
  "description": {
    "element": {
      "type": "div",
      "props": {
        "className": "__custom-description"
      },
      "render": (props) => {
        return `<div>
              <div>Workflow: First 5 images</div>
              <div>Explanation of Isolation</div>
            </div>`
      }
    }
  }
}
```

Then you can pass the `CustomPriceDescription` to the config options.

```javascript
/** Add the CustomPriceDescription element
 to Billflow Config options like this. */
{
  billing_page_id: "TMXnsJS2S7odVGyIW5Qc",
  options: {
    elements: {
      checkout: {
        prices: [
          CustomPriceDescription, // the custom price description element created above
        ]
      }
    }
  }
}

```

[Checkout the full example code here.](https://codepen.io/kslung/pen/KKmozzy)

### Checkout: Price Item Price

This section describes how you can customize the **Price** within the checkout view like the following example.

{% embed url="<https://codepen.io/kslung/pen/mdmxPrV?editors=1100>" %}
Customized checkout price highlighted in red
{% endembed %}

To customize a checkout price, you will first create a custom element like this.

```javascript
const CustomCheckoutPrice = {
  id: "price_HDa0zWHKXsY2sb", // replace with your own Stripe price id
  price: {
    element: {
      type: "div",
      props: {
        className: "__custom-amount"
      },
      render: (props) => {
        const { unit_amount, currency, formatters } = props;
        const amount = formatters.price({
          amount: unit_amount,
          currency
        });
        return `<div>
            <div>${amount} / mo.</div>
            <div>additional images</div> 
          </div>`;
      }
    }
  }
};
```

Then you can pass the `CustomCheckoutPrice` to the config options.

```javascript
/** Add the CustomCheckoutPrice element
 to Billflow Config options like this. */
{
  billing_page_id: "TMXnsJS2S7odVGyIW5Qc", // replace with your own billing page id
  options: {
    elements: {
      checkout: {
        prices: [
          CustomCheckoutPrice, // the custom checout price
        ] 
      }
    }
  }
}
```

[Checkout the full example code here.](https://codepen.io/kslung/pen/mdmxPrV)


# Versions & Beta Testing

## Billing Page Version

When a major update is released, the version is incremented and this becomes available on the billing page. You are not automatically put on the newest version as these can present changes that could cause unwanted changes. These changes will usually be style related. Make sure to test out version updates before changing your production billing page.&#x20;

{% hint style="info" %}
No changes are needed to your code snippet or implementation unless explicitly noted
{% endhint %}

![Billing Page version on top right](/files/-MSe0kqUqOuBiBtkWd5-)

## Beta Testing

If you are looking to test out new functionalities or views with your current integration to make sure they do not break your existing set up, follow the steps below. Updates are pushed to a beta url, so just changing that url on your embed snippet.&#x20;

In the Billflow embed snippets you will see a line where the source is pulled in&#x20;

```
s.src = 'https://js.billflow.io/billflow-embed.js';
```

Change that to the following beta link to test out the newest release.

```
s.src = 'https://js.billflow.io/beta/billflow-embed.js';
```


# Managing Account & Team

Account management

Guides on managing your account, team members, and billing.

{% content-ref url="/pages/-MGTUq8w8eH00rm0IbmF" %}
[Reset Your Password](/help/manage-your-account/reset-your-password)
{% endcontent-ref %}

{% content-ref url="/pages/-MGTUuZl852018yIUbLP" %}
[Manage Team Members](/help/manage-your-account/manage-team-member)
{% endcontent-ref %}


# Reset Your Password

Reset password steps

## **Logged out**

In order to reset your password go to <https://dashboard.billflow.io/login> and select **Forgot your password?**

![](/files/-MR0k7Fl-4kp8Ef8a7Z0)

Enter in your email and an email will be set with your password reset link.

{% hint style="info" %}
Not receiving a link or still not able to log in? Please message us with the chat link below.
{% endhint %}

## Logged in

If you are logged in, you can click the profile button on the top right of the dashboard. From there you will click **Change Password** and set your new password.

![Account button](/files/-MJ4CH40ZQMHNmZj3Z-S)


# Manage Team Members

Team Management Steps

## Invite new team members

Select **Team** on the side bar navigation on the dashboard to manage your team members. Then select **+ Add New Team Member**.&#x20;

Enter their **Name**, **Email**, **Role**, and select **Invite**.

There are two sets of permissions that can be granted to an invited member. The first is Admin which is able to access the ‘account’ section and the other is Non-Admin who have access to everything but the ‘account’ section. As this is separate from Stripe, your team members won’t have access to the Stripe account-- although linking them  may be useful.

![Invite Team Members](/files/-MIa40Hi_tmSIBNF47jY)

## Remove team member access

To remove a team member, simply click the Trash icon. Confirm in the pop up modal and they will be removed from the account.


# Frequently Asked Questions

## Is Billflow GDPR compliant?

Yes, Billflow is GDPR Compliant. Billflow only stores customer email and some Stripe IDs. All other data remains in Stripe and your system. If you receive a request to remove a user's data, simply delete them from Stripe and it will automatically remove their email from Billflow.

## Can I create a lifetime subscription?

Yes, to create a lifetime subscription, just add a product to your service that is a one-time payment.

## Can I connect a test Stripe account?

Currently you must have a fully complete Stripe account with bank details in order to connect to Billflow. If you wish to test around, check out our [examples page](https://dashboard.servicebot.io/examples) to see how the billing pages look and how they are installed.&#x20;

## Can I use the Customer Portal for my existing Stripe customers?

Yes, absolutely. Billflow looks up your customer's subscriptions by email or Stripe Customer ID. Subscriptions can be created from the Stripe Dashboard, via the API, Third-party app, or from Billflow and the Customer Portal can still show them.

## How do I unlink Stripe to connect a different account?

You can unlink your Stripe account from Billflow by clicking "Connected to Stripe" on the dashboard which will take you to the [Stripe Accounts Page](https://dashboard.stripe.com/account/applications).&#x20;

![](/files/-MR5DfYqC2oNOLfZtL1V)

Select "Revoke Access" for Billflow and your account will no longer be connected. When you go back to the dashboard, refresh the page and you should be able to Connect again to a different account.&#x20;

{% hint style="danger" %}
This will delete your current billing pages
{% endhint %}


# Changelog

Product releases and changes

Check out our product updates [here](https://servicebot-updates.bubbleapps.io/)


