Shopify’s default product purchase flow routes through the Cart page, but what if you want customers to instantly buy a product via a "Book Now" button — skipping the cart entirely?
In this blog, we’ll walk through how to implement a custom direct checkout button for single products using a Shopify custom snippet and basic Liquid code.
Step-by-Step Implementation
Step 1: Open Your Shopify Store
-
Log into your Shopify admin panel.
- Go to Online Store → Themes.
- Click “Edit code” for the theme you want to modify.

Step 2: Create a New Snippet
- In the Snippets folder, click Add a new snippet.
- Name it:

- Paste the following code inside buy-buttons-custom.liquid:
{% comment %}
Renders product buy-buttons.
Accepts:
- product: {Object} product object.
- block: {Object} passing the block information.
- product_form_id: {String} product form id.
- section_id: {String} id of the section to which this snippet belongs.
- show_pickup_availability: {Boolean} for the pickup availability. If true the pickup availability is rendered, false - not rendered (optional).
Usage:
{% render 'buy-buttons', block: block, product: product, product_form_id: product_form_id, section_id: section.id, show_pickup_availability: true %}
{% endcomment %}
<div {{ block.shopify_attributes }}>
{%- if product != blank -%}
{%- liquid
assign gift_card_recipient_feature_active = false
if block.settings.show_gift_card_recipient and product.gift_card?
assign gift_card_recipient_feature_active = true
endif
assign show_dynamic_checkout = false
if block.settings.show_dynamic_checkout and gift_card_recipient_feature_active == false
assign show_dynamic_checkout = true
endif
-%}
<product-form
class="product-form"
data-hide-errors="{{ gift_card_recipient_feature_active }}"
data-section-id="{{ section.id }}"
>
<div class="product-form__error-message-wrapper" role="alert" hidden>
<span class="svg-wrapper">
{{- 'icon-error.svg' | inline_asset_content -}}
</span>
<span class="product-form__error-message"></span>
</div>
{%- form 'product',
product,
id: product_form_id,
class: 'form',
novalidate: 'novalidate',
data-type: 'add-to-cart-form'
-%}
<input
type="hidden"
name="id"
value="{{ product.selected_or_first_available_variant.id }}"
{% if product.selected_or_first_available_variant.available == false
or quantity_rule_soldout
or product.selected_or_first_available_variant == null
%}
disabled
{% endif %}
class="product-variant-id"
>
{%- if gift_card_recipient_feature_active -%}
{%- render 'gift-card-recipient-form', product: product, form: form, section: section -%}
{%- endif -%}
<div class="product-form__buttons">
{%- liquid
assign check_against_inventory = true
if product.selected_or_first_available_variant.inventory_management != 'shopify' or product.selected_or_first_available_variant.inventory_policy == 'continue'
assign check_against_inventory = false
endif
if product.selected_or_first_available_variant.quantity_rule.min > product.selected_or_first_available_variant.inventory_quantity and check_against_inventory
assign quantity_rule_soldout = true
endif
-%}
{{ form | payment_button }}
</div>
{%- endform -%}
</product-form>
{%- else -%}
<div class="product-form">
<div class="product-form__buttons form">
<button
type="submit"
name="add"
class="product-form__submit button button--full-width button--primary"
disabled
>
{{ 'products.product.sold_out' | t }}
</button>
</div>
</div>
{%- endif -%}
{%- if show_pickup_availability -%}
{{ 'component-pickup-availability.css' | asset_url | stylesheet_tag }}
{%- assign pick_up_availabilities = product.selected_or_first_available_variant.store_availabilities
| where: 'pick_up_enabled', true
-%}
<pickup-availability
class="product__pickup-availabilities quick-add-hidden"
{% if product.selected_or_first_available_variant.available and pick_up_availabilities.size > 0 %}
available
{% endif %}
data-root-url="{{ routes.root_url }}"
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
data-has-only-default-variant="{{ product.has_only_default_variant }}"
data-product-page-color-scheme="gradient color-{{ section.settings.color_scheme }}"
>
<template>
<pickup-availability-preview class="pickup-availability-preview">
<span class="svg-wrapper">
{{- 'icon-unavailable.svg' | inline_asset_content -}}
</span>
<div class="pickup-availability-info">
<p class="caption-large">{{ 'products.product.pickup_availability.unavailable' | t }}</p>
<button class="pickup-availability-button link link--text underlined-link">
{{ 'products.product.pickup_availability.refresh' | t }}
</button>
</div>
</pickup-availability-preview>
</template>
</pickup-availability>
<script src="{{ 'pickup-availability.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
</div>
Note:
-
This form posts directly to /checkout instead of adding to cart.
-
Adjust styles and validations as needed.
Step 3: Modify card-product.liquid or Relevant Product Card File
- Locate your product card snippets — usually named something like card-product.liquid
-
Find this block of code (or similar):
<div class="card card--{{ settings.card_style }}"
-
After the closing </div> of this card, paste the following code:
<div class="book-now-button">
{%- assign product_form_id = 'product-form-' | append: section.id -%}
{%- render 'buy-buttons-custom',
block: block,
product: card_product,
product_form_id: product_form_id,
section_id: section.id,
show_pickup_availability: true
-%}
</div>

Step 5: Change Default Payment Button Text to “Book Now”
Shopify’s dynamic checkout button (used by Shop Pay, Apple Pay, GPay, etc.) may still show branded labels. If you're using the unbranded version, you can override the label like this:
Open:
layout/theme.liquid
1. Inside the <head> tag (before </head>), paste this:
<style>
.shopify-payment-button .shopify-payment-button__button--unbranded {
position: relative;
}
.shopify-payment-button .shopify-payment-button__button--unbranded:after {
content: "Book Now";
background: inherit;
font-size: inherit;
color: inherit;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.shopify-payment-button .shopify-payment-button__button--unbranded > span {
visibility: hidden;
}
</style>

You’ve successfully implemented a direct checkout button that:
-
Instantly sends the product to checkout.
-
Skips the cart page.


Conclusion
By adding a custom “Book Now” button that skips the cart and leads directly to checkout, you’ve created a faster and more focused shopping experience
This simple customization gives your Shopify store a professional edge by reducing friction and helping customers complete purchases with fewer clicks.
WhatsApp