SureBooking — User Guide

Technical & System Operations Documentation
Appointment Management Service Booking

View, filter, and manage all service appointments. Each appointment can contain one or more service details, assigned employees, and payment information.

Access: Admin Booking Service Appointments
Search Filters
Filter Field Description
Date Range Filter by appointment date (from date – to date).
Branch Filter by service branch/location.
Status Filter by appointment status: Draft, New, Accepted, Success, Cancel.
Employee Filter by assigned employee.
Customer Search by customer name or phone number.
Appointment Statuses
Status Value Description
Draft -1 Appointment created but not yet confirmed by customer or admin.
New 1 Customer has submitted the appointment; awaiting admin confirmation.
Accepted 4 Admin has accepted the appointment. Service will be performed as scheduled.
Success 3 Service has been completed successfully.
Cancel 2 Appointment has been cancelled by admin or customer.
Appointment Detail Actions
  • Change Status — Move the appointment through allowed status transitions.
  • Add History Note — Record internal notes or status change reasons in the appointment timeline.
  • Edit Customer Info — Update the customer's name, phone, or notes linked to this appointment.
  • View Payment — See linked payment details, amount, and payment channel.
  • Contact Info Log — If the booking email matches an existing account but the submitted name/phone differs, the system logs a contact_info_submitted history entry for review.
Clicking any row in the appointments list opens the appointment detail page, showing all services, employee assignments, timeline history, and payment status.
Branch Management Service Booking

Manage your salon or spa locations. Each branch has its own set of services, employees, and booking schedules.

Access: Admin Booking Service Branches
Branch Fields
Field Required Description
Name Yes Display name of the branch.
Slug Yes URL-friendly identifier. Used in the booking page URL.
Address Optional Physical address of the branch.
Phone Optional Contact phone number for the branch.
Image Optional Cover image displayed on the branch booking page.
Status Yes Active — Branch is bookable. Inactive — Branch is hidden from the booking flow.
After creating a branch, go to Services to create service categories linked to that branch, then assign employees via Employees → Branch Map.
Service Management Service Booking

Create and manage the services offered at your branches. Services are grouped by category and linked to a branch.

Access: Admin Booking Service Services
Service Fields
Field Required Description
Name Yes Service name displayed to customers.
Slug Yes URL-friendly identifier for the service.
Category Yes Service category, which is linked to a branch.
Price Optional Base price of the service. Enable "Price From" to display as a starting price range.
Duration Optional Estimated service duration in minutes. Used for scheduling time slots.
Image Optional Service thumbnail displayed on the booking page.
Status Yes Active — Service is bookable. Inactive — Hidden from customers.
Services can have Variants (e.g., different durations or prices) and can be assigned to specific employees. Employees assigned to a service will appear as options during the booking flow.
Customer Management Service Booking

View all customers who have made bookings. Customers are user accounts created automatically during the booking flow.

Access: Admin Booking Service Customers
Customer List Columns
Column Description
Name Customer's full name.
Email Customer's email address used for account and booking notifications.
Phone Customer's phone number.
Guest Indicates if the customer is a guest account (auto-created during booking, has not yet set their own password).
Total Appointments Number of bookings this customer has made.
Created Date Date the customer account was created.
Customers cannot be created manually from admin. Accounts are created automatically when a guest books using an email address for the first time. If the email already belongs to an account, the booking is linked to that existing account without overwriting any data.
Booking Dashboard Service Booking

Overview charts and statistics for appointment activity, revenue, employee performance, and popular services.

Access: Admin Booking Service Dashboard
Available Charts
Chart Description
Total Appointments Total number of appointments over the selected date range, broken down by status.
Revenue Total revenue from completed appointments over the selected date range.
Employee Performance Revenue and appointment count per employee. Filter by date range to see individual performance.
Popular Services Most frequently booked services, ranked by appointment count.
Time Slot Distribution Booking frequency by time slot, useful for identifying peak hours.
Coupons Service Booking

Create and manage discount coupons applied at booking checkout. Supports fixed-amount and percentage discounts, scoped to all bookings, specific customers, service categories, services, or branches.

Access: Admin Booking Service Coupons
Search & Filters
Filter Description
Coupon Name Partial search by coupon name.
Coupon Code Exact or partial match on the code string entered by customers.
Status Filter by Active or Inactive.
Coupon Form Fields
Field Required Description
Coupon Name Required Display name for internal management.
Coupon Code Required Unique code customers enter at checkout. Must be unique system-wide. Case-insensitive matching recommended.
Discount Type Required Amount (fixed) — deduct a fixed amount from the total.
Percent (%) — deduct a percentage of the applicable subtotal.
Discount Value Required The amount or percentage to deduct. Must be ≥ 0.
Max Discount Value Optional Only applies when Discount Type is Percent. Caps the maximum discount amount. Leave 0 for no cap.
Minimum Order Value Optional The minimum booking total required before this coupon can be applied. Leave 0 for no minimum.
Quantity Required Total number of times this coupon can be used across all customers. Set to 0 for unlimited uses.
Start Date Optional Date from which the coupon becomes valid. If not set, valid immediately upon activation.
End Date Optional Date after which the coupon expires. If not set, the coupon never expires.
Applicable Object Required Determines which bookings the discount applies to (see table below).
Thumbnail Image Optional Image shown in the customer-facing coupon list.
Note Optional Internal admin note — not shown to customers.
Status Required Active — coupon is usable. Inactive — coupon is disabled and rejected at checkout.
Applicable Object — Scope Rules
Scope How the Discount is Calculated
All apply_to = 0 Discount applied on the entire booking total. Any customer can use it.
Customer apply_to = 1 Only specific customers (selected by name/account) can redeem. Discount applies to the full booking total. Requires the customer to be logged in.
Service Category apply_to = 2 Discount calculated only on the subtotal of services belonging to the selected categories. Other services in the same booking are not discounted.
Service apply_to = 3 Discount calculated only on the subtotal of the selected services (or their specific variants). Services not in the list are excluded from the discount base.
Branch apply_to = 4 Discount applies to the entire booking total, but only when the customer books at one of the selected branches.
Validation Rules at Checkout

When a customer enters a coupon code during booking, the system validates in order:

  1. Code exists & status is Active — invalid or inactive codes are rejected immediately.
  2. Applicable Object scope — if scoped to a specific customer, the customer must be logged in and match.
  3. Start Date / End Date — coupon must be within its validity window.
  4. Per-user usage — each customer (by user account or guest session) can only use the same coupon once.
  5. Total quantity — remaining uses must be > 0 (if quantity ≠ 0).
  6. Minimum order value — booking total must meet or exceed min_order.
  7. Discount calculation — discount computed on the applicable subtotal; capped at max_value for percent type.
Coupons are applied at booking submission, not at preview. The system stores the coupon ID in the session during the booking flow and finalizes the discount atomically (with a DB lock) when the appointment is created.
Admin booking: Admin can also apply a coupon when creating an appointment on behalf of a customer via the admin booking form. The system validates the coupon and customer eligibility using the customer's phone number.
Coupon Usage History Service Booking

Track every coupon redemption — which customer used which code on which appointment, the discount amount, and the usage status.

Access: Admin Booking Service Coupon Usage
Usage Record Fields
Field Description
Coupon Code The code that was redeemed.
Appointment Link to the appointment this coupon was applied to.
Customer The user account that applied the code (empty for anonymous/guest checkouts).
Total Before Original booking total before the discount was applied.
Total After Booking total after the discount. Discount value = Total Before − Total After.
Discount Type 1 = Fixed amount, 2 = Percent.
Discount Value The raw coupon value at time of use (amount or percent figure).
Status 1 — Used: discount has been confirmed and applied.
2 — Pending: coupon reserved but appointment not yet finalized.
3 — Cancelled: appointment was cancelled; coupon returned to pool.
-1 — Rolled back: system-level rollback (e.g., payment failure).
When an appointment is cancelled, the system automatically rolls back any associated coupon usage (status → -1), freeing that usage slot so the coupon quantity is restored.
API Token — Overview & Authentication API

The API Token module allows third-party applications to access booking data via a REST API. All endpoints require Sanctum token authentication and are subject to rate limiting.

Access: Admin API Token
Generating a Token
  1. Go to Admin → API Token.
  2. Click "Create New API Client". Enter a client name, set the rate limit (requests per minute), and save.
  3. Copy the generated token — it will only be shown once.
  4. Use the token in the Authorization header of every API request.
Authentication Header

Include this header in every API request:

Authorization: Bearer {your_api_token}
Content-Type: application/json
Common Response Format
{
  "success": true,
  "data": [ ... ],
  "meta": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 15,
    "total": 72
  }
}

Error responses return "success": false with a "message" field and an appropriate HTTP status code (404, 422, 500).

All API requests are rate-limited per token. Exceeding the limit returns HTTP 429 Too Many Requests. Configure the limit when creating the API client.
Appointments API API

Read and update appointment data via API.

GET /api/v1/appointments

List appointments with optional filters.

Parameter Type Description
status int Filter by status: -1 Draft, 1 New, 2 Cancel, 3 Success, 4 Accepted.
date_from date Filter appointments on or after this date. Format: YYYY-MM-DD.
date_to date Filter appointments on or before this date. Format: YYYY-MM-DD.
branch_id int Filter by branch ID.
per_page int Items per page. Default: 15. Max: 100.
page int Page number. Default: 1.
GET /api/v1/appointments/{id}

Get full detail of a single appointment including services, employees, and payment.

Response fields: id, code, status, statusText, dateAppointment, timeStart, timeEnd, totalPrice, note, branch, customer, details[] (service, employee, price, duration), payment, createdAt.

PATCH /api/v1/appointments/{id}/status

Update the status of an appointment. Only valid transitions are accepted.

// Request body
{
  "status": 4,         // required — target status value
  "reason": "..."      // optional — reason note for cancel
}
Current Status Allowed Transitions
Draft (-1) → New (1)
New (1) → Accepted (4)  |  Cancel (2)
Accepted (4) → Success (3)  |  Cancel (2)
Branches API API

Read branch (location) data.

GET /api/v1/branches

List active branches. Only returns branches with status = Active.

Parameter Type Description
search string Search by branch name.
per_page int Items per page. Default: 15. Max: 100.
page int Page number.

Response fields: id, name, slug, address, phone, image, status, createdAt.

GET /api/v1/branches/{id}

Get details of a single active branch by ID. Returns 404 if not found or inactive.

Services API API

Read service data. Filter by branch to get only the services available at a specific location.

GET /api/v1/services

List active services. Pass branch_id to get all services available at a specific branch (bypasses pagination).

Parameter Type Description
search string Search by service name.
branch_id int Return all services for this branch (no pagination).
per_page int Items per page. Default: 15. Max: 100.
page int Page number.

Response fields: id, name, slug, image, price, duration, status, category (id, name).

GET /api/v1/services/{id}

Get details of a single active service by ID, including its category. Returns 404 if not found or inactive.

Customers API API

Read customer (user) data for customers who have at least one booking.

GET /api/v1/customers

List customers with optional search.

Parameter Type Description
search string Search by name, email, or phone number.
per_page int Items per page. Default: 15. Max: 100.
page int Page number.

Response fields: id, name, email, phone, isGuest (boolean — true if the account was auto-created during booking and the user has not yet set a password), createdAt.

GET /api/v1/customers/{id}

Get details of a single customer by ID. Returns 404 if not found.

Guest accounts (isGuest: true) are created automatically when someone books without an existing account. They can set their own password via the Change Password page, at which point isGuest becomes false.
Post List Posts

View, search, filter and manage all published posts.

Access: Admin Posts All Posts Open page
List page interface

The list page displays all posts in a table format, including: post title, author, category, published date, SEO score and status.

Search filters
Filter field Description
Post title Search by post title (partial match).
Slug Search by the post's SEO-friendly URL.
Category Filter posts by a specific category.
Created date Filter by post date range (from date → to date).
Status Filter by Active / Inactive / Trash.
Post actions
Action Description
Edit Click the post title or pencil icon to go to the edit page.
Duplicate Copy all post content to a new draft for editing.
Delete / Restore Move the post to trash. Can be restored or permanently deleted from the Trash tab.
Bulk status change Select multiple posts → choose action → Apply.
Export Excel Export the post list to an .xlsx file (requires posts_exports permission).
Add New Post Posts

Create and publish a new post on the system.

Access: Admin Posts Add Post Open page
Post information
Field Required Description
Title ✓ Required The post title, displayed on the website interface and the <title> tag.
Slug (URL) ✓ Required SEO-friendly URL. Auto-generated from the title; can be edited manually.
Short description Optional Post excerpt, commonly used for listing pages and the meta description tag.
Content ✓ Required Full post content. Edited with a WYSIWYG editor.
Thumbnail Optional Thumbnail image displayed in listings and as the OG image when sharing on social media.
Category Optional Select one or more categories for the post.
Author Optional Select the author from the admin user list. Defaults to the logged-in user.
Language Optional Select the post language if the system runs in multi-language mode.
Featured Optional Mark the post as featured (highlighted) to prioritize its display.
Status ✓ Required Active = visible, Inactive = hidden from website.
SEO Tab
Field Description
SEO Title A separate SEO title, different from the post title (if you want to optimize for a different keyword).
SEO Description Meta description displayed in Google search results. Recommended: 150–160 characters.
SEO Keywords SEO keywords for the post (has little impact on current rankings).
Tip: The SEO score (SEO Point) is calculated automatically based on the title, description and content. Aim for a green score (≥ 70) for the most optimized post.
Steps to publish a new post
  1. Go to Posts → Add Post.
  2. Enter the Title. The Slug will be auto-generated; edit if needed.
  3. Write the Content in the editor. Upload images directly into the editor or via the Media Library.
  4. Select a Category and upload a Thumbnail.
  5. Fill in SEO Title and SEO Description in the SEO tab.
  6. Set the status to Active and click Save.
After adding a post, you need to Clear cache (the lightning icon in the header bar) so the latest post appears on the website.
Post Categories Posts

Organize posts by topic or subject area.

Access: Admin Posts Categories Open page
Category fields
Field Required Description
Category name ✓ Required The display name of the category on the website.
Slug ✓ Required Category URL. Auto-generated from the name, e.g.: tin-tuc.
Parent category Optional Select a parent category to create a subcategory structure.
Description Optional Short description for the category, typically displayed on the category listing page.
Thumbnail Optional Thumbnail image representing the category.
Status ✓ Required Active to display the category on the website.
Categories support a multi-level parent–child structure. When a parent category is deleted, child categories are NOT deleted but are instead detached and become root categories.
Post Settings Settings

Configure the display and behavior of the post module: sidebar, comments, SEO schema, "read more" button and default news page. Configuration is saved with setting_name = 'post_setting'.

Access: Admin Settings Posts Open page
Setting options
Option Default Description
Show Sidebar Yes Enable/disable sidebar widget on the post detail page and category pages. Helper: BlogHelper::isSidebarEnabled().
Allow comments Yes Enable/disable comments on all posts. When disabled, the comment form is completely hidden even if the Comment module is active. Helper: BlogHelper::isCommentEnabled().
Show Default Schema Yes Automatically inject JSON-LD Schema.org (Article / NewsArticle) into the <head> of the post detail page to optimize SEO and rich results. Helper: BlogHelper::isSchemaEnnabled().
"Read more" button No Display a content truncation button — long posts are cut after X characters with a "Read more" button to expand. Helper: BlogHelper::isViewMoreEnnabled().
Select news page Link to the Page that will display the post list. The system uses this ID to build the breadcrumb and hierarchical URL. Helper: BlogHelper::blogPageId().
Posts per page (Pagination)

The number of posts displayed on the list and category pages is configured at Settings → Reading Settings, field "Posts per page".

The Post module injects this field into the Reading Settings page via the hook BASE_FILTER_ADD_PAGINATION_CONFIG with key post_paginate, default value 10. In code, retrieve it with: $readingConfig['post_paginate'] ?? 10.

Select news page: You must first create a Page using the post list template, then select that page's ID here. If left blank, the post detail breadcrumb will not have a "Blog" level link and category URLs may display incorrectly.
Static Page List Static Pages

View, search, filter and manage all static pages on the system.

Access: Admin Static Pages All Static Pages Open page
List page interface

The list page displays all static pages in a table format, including: page name, URL (slug), order, SEO score and status.

Search filters
Filter field Description
Page name Search by static page title (partial match).
Slug Search by the page's SEO-friendly URL.
Created date Filter by page creation date range (from date → to date).
Status Filter by Active / Inactive / Trash.
Static page actions
Action Description
Edit Open the static page content edit form.
Delete Move the page to trash. Can be restored or permanently deleted afterward.
View on site Open the static page on the website in a new tab.
To bulk delete, select multiple pages and use the Bulk Actions button above the table.
Add / Edit Static Page Static Pages

Create a new static page or edit an existing page's content.

Access: Admin Static Pages Add New Page Open page
Static page information
Field Required Description
Title ✓ Required Page name, displayed in menus, breadcrumbs and the <title> tag.
Slug (URL) ✓ Required SEO-friendly URL. Auto-generated from the title; can be edited manually. Example: gioi-thieu.
Content Optional Full page content. Edited with a WYSIWYG editor.
Thumbnail Optional Thumbnail image displayed when sharing the page on social media (OG image).
Language Optional Select the page language if the system runs in multi-language mode.
Status ✓ Required Active — visible on website; Inactive — hidden from website.
SEO Tab
SEO field Description
SEO Title Title displayed in Google search results. Recommended: under 60 characters.
Meta Description Short description for Google. Affects click-through rate. Recommended: under 160 characters.
Meta Keywords Keywords related to the page content (little effect on modern SEO).
Steps to create a static page
  1. Go to Static Pages → Add New Page.
  2. Enter the Title — a slug will be automatically generated.
  3. Write the Content with the editor.
  4. Switch to the SEO tab to fill in the SEO Title and Meta Description.
  5. Select a Status and click Save.
For the page to appear on the website menu, after saving go to Menu and add the page to the desired position.
The Slug must be unique across the entire system. If the slug duplicates another page, the system will return an error when saving.
General Settings (Header / Footer / 404) Theme

Configure header, footer, and custom 404 page information. This page has 3 configuration tabs.

Access: Admin Theme General Settings Open page
Tab 1 — Header Configuration
Field Required Description
Header phone number Optional Hotline displayed on the top header bar.
Quick Search — Products Optional List of suggested products appearing in the quick search box in the header.
Quick Search — Articles Optional List of suggested articles in the quick search box.
Popular keywords Optional List of keywords + links displayed below the header search box. Each item includes: Keyword name and Link.
Tab 2 — Footer Configuration
Field Required Description
Footer form Optional Select a registration form (from the Custom Forms feature) to display in the footer.
Company name Optional Business name displayed in the footer.
Company address Optional Headquarters address displayed in the footer.
Company phone number Optional Hotline displayed in the footer.
Company email Optional Contact email displayed in the footer.
DMCA Link / Image Optional Copyright protection badge: enter the DMCA badge link and image.
Copyright Optional Copyright line displayed at the bottom of the footer. Can be plain text or HTML format.
Tab 3 — 404 Error Page Configuration
Field Required Description
404 Title Optional Large title displayed on the 404 error page.
404 Description Optional Short explanatory paragraph below the 404 title.
Redirect suggestion list Optional Suggested navigation items when the user visits a non-existent link. Each item includes: Title, Description, Button name, and Link.
This page supports multilingual — select the language in the top right corner to enter content for each language separately.
Theme Configuration Theme

An overview of all configuration pages within the Theme menu group (parent: group_interface).

Access: Admin Theme Theme Configuration Open group page
Configuration list in the Theme group
Configuration item Main function
Font, size, color & logo configuration Set overall style: typography, primary color, header/footer display configuration by layout, logo and style for desktop/mobile.
Menu Manage website navigation menu structure, arrange order, assign links, and configure menu display.
CSS Enter custom CSS to override the theme interface per specific needs without editing the theme source directly.
Sidebar widgets Manage widgets in the sidebar/footer area: add, arrange, and configure content blocks to display.
Menu Management Theme

Create and configure navigation menus displayed on the website (header, footer, mobile...).

Access: Admin Theme Menu Open page
Create new menu
  1. Enter the Menu name and click Create menu.
  2. Add items to the menu: select from Pages, Articles, Categories, Custom links...
  3. Drag and drop to reorder and create sub-menus.
  4. Assign the menu to a display location (Menu location).
  5. Click Save menu.
Menu Locations
Location Description
Main menu (Desktop) Primary navigation menu on the desktop header.
Mobile menu Navigation menu dedicated to mobile devices.
Footer menu Menu placed in the footer area.
Customize menu items

Each menu item can be further customized:

  • Display title — set a custom display name instead of the default name.
  • Icon — assign an icon to the menu item.
  • CSS class — for custom styling (for those familiar with CSS).
  • Open in new tab — enable to open the link in a new tab.
Multiple menus can be created and each assigned to a different location. Menus that have not been assigned will not be displayed on the website.
Custom CSS Theme

Add custom CSS or JavaScript to the website without editing the theme files directly.

Access: Admin Theme CSS Open page
Custom CSS

Write custom CSS in the editor area. The CSS will be automatically applied to the entire website.

  • Change the interface without editing theme files.
  • Change fonts, colors, spacing per project requirements.
  • Show/hide specific elements.
Access: Admin Theme Embed Open page
Custom JS

Inject custom JavaScript. The JS will be automatically added to the end of the page.

  • Add tracking code (Google Analytics, Facebook Pixel...).
  • Integrate livechat, chatbot.
  • Other custom scripts.
No need to add wrapper tags — just enter the CSS / JS content directly into the editor. The system will handle the rest.
This page is intended for users with knowledge of CSS / JavaScript. If unfamiliar, please ask a technician for assistance to avoid incorrect input that may affect the website interface.
Website Information Settings

Configure basic website information: company name, email, phone number, address, description, and copyright. This information is used across many modules: email, footer, shortcode.

Access: Admin Settings Overview Open page
Configuration fields
Field Type Description
Company name text Brand / company name displayed on the website and in emails.
Email text Website's representative email. Used in system email templates.
Phone number text Primary contact phone number.
Hotline text Customer support Hotline number.
Address text Office / store address.
Description textarea Short description of the website / business.
Copyright textarea Copyright content displayed in the footer.
Data is saved with setting_name = 'overview'. Can be read in code using getSiteName(), getSiteDescription() or getOption('overview').
Email Configuration Settings

Set up the SMTP server for the system to send notification emails, appointment confirmations, and status updates. Includes a test email feature to verify the configuration.

Access: Admin Settings Email → Server Configuration Open page
SMTP Configuration
Field Type Description
Protocol select Currently supports SMTP.
SMTP Host text SMTP server address. Example: smtp.gmail.com, smtp.sendgrid.net.
SMTP Port text Connection Port. Usually 587 (TLS) or 465 (SSL).
Encryption select TLS or SSL.
Username text SMTP username (usually the email address).
Password password SMTP password or App Password (for Gmail, 2FA must be enabled and an App Password created).
Charset text Character set. Default utf-8.
From Address text Sender email address displayed in the recipient's inbox.
From Name text Sender display name. Example: Dream Team.
Reply-To text Email to receive replies when the user clicks Reply. Leave blank to use From Address.
Test email

After saving the configuration, enter an email address in the "Send test email" field and click the test button. The system sends a sample email to that address immediately.

  • If you receive the email → SMTP configuration is correct.
  • If not received → check host, port, encryption, and App Password again.
Email content templates

Customize HTML content for each type of system email (appointment confirmation, status change...) at:

Settings Email → Email content templates Open page
For Gmail, you must use an App Password instead of your regular password. Go to myaccount.google.com → Security → App passwords to create one.
Embed Code Settings

Inject Google Analytics, Facebook Pixel, Google Tag Manager scripts or any code snippet into the <head> or <body> of all pages. Includes an option to delay script loading to improve page speed.

Access: Admin Settings Embed Code Open page
Embed positions
Field Description
HTML Head (No Script) Inject at the end of <head> as <noscript> — used for GTM noscript tags or pixels that don't need JS.
HTML Head Inject at the end of <head> — used for Google Analytics, GTM scripts, verification meta tags.
HTML Body (Footer) Inject before </body> — used for chat widgets, pixels, scripts initialized after DOM.
Delay Load Script

This feature delays the execution of injected scripts until the user interacts with the page (scroll, click, mouse move). This helps improve Core Web Vitals and PageSpeed scores.

Option Description
Enable delay Toggle to enable/disable the delay feature. When disabled, scripts run as soon as the page loads.
Delay time (seconds) If the user does not interact, scripts will still run after exactly this many seconds. Default is 10 seconds.
To install Google Analytics 4: paste the <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"> snippet into HTML Head. To install GTM: paste the script into HTML Head and the noscript into HTML Head (No Script).
Reading Settings Settings

Configure the homepage, pagination, asset version and no-index options for the entire website.

Navigate to: Admin Settings Reading Settings Open page
Configuration fields
Field Type Description
Homepage select Select a CMS page to use as the homepage. The selected page will be mapped to the URL /.
Items per page (pagination) number Number of items displayed per page on listing pages (posts, products...). Modules can register their own pagination config via the filter BASE_FILTER_ADD_PAGINATION_CONFIG.
Asset Version number Asset version (CSS/JS). Increment this number to force browsers to reload the latest asset files (cache busting). Defaults to the value from cms_assets.version.
No-index checkbox Enable to add <meta name="robots" content="noindex"> to all pages — typically used in staging/dev environments to prevent Google from indexing.
Enabling No-index on the production environment will prevent Google from crawling the entire website. Only use this in dev/staging environments.
reCAPTCHA Settings

Configure Google reCAPTCHA v2 for use across the entire system — protects booking forms, contact forms, and customer-facing forms from spam and bots.

Navigate to: Admin Settings reCAPTCHA Open page
Configuration fields
Field Type Description
Enable reCAPTCHA toggle Enable/disable reCAPTCHA across the entire system. When enabled, two additional key fields will appear below.
Site Key text Public key embedded into the frontend page to display the reCAPTCHA widget.
Secret Key text Secret key used server-side to verify the response from Google. Never expose this on the frontend.
How to obtain Site Key & Secret Key
  1. Go to google.com/recaptcha/admin/create.
  2. Enter a name for the site, select the type reCAPTCHA v2 → "I'm not a robot".
  3. Add your website's domain to the allowed list.
  4. Click Submit — Google will provide the Site Key and Secret Key.
  5. Copy both keys into the settings form and save.
Application scope

Once enabled and configured, reCAPTCHA is automatically applied at the following points:

  • Booking form — customer appointment booking page.
  • Contact form — customer enquiry / contact page.
reCAPTCHA is only displayed when all 3 conditions are true: toggle enabled, Site Key has a value, Secret Key has a value. If any one is missing, the widget will not appear and the form allows normal submission.
Read reCAPTCHA status in PHP code using the function isRecaptchaEnabled() and get the key with getRecaptchaConfig('key') / getRecaptchaConfig('secret').
Call-to-Action Button (CTA) Settings

Configure floating contact buttons on the website: Zalo, Facebook, Phone, WhatsApp, Messenger... Admin sets up links, descriptions and display types.

Navigate to: Admin Settings Call-to-Action Button Open page
Support contact channels

Each channel is an independent list of accounts (you can add multiple phone numbers, multiple Zalo accounts...). Each item includes:

Channel Example link
Facebook https://facebook.com/yourid
Zalo https://zalo.me/0912345678
Phone tel:0912345678
WhatsApp https://wa.me/84912345678
Viber viber://chat?number=+84912345678
Messenger https://m.me/yourpage
Instagram https://instagram.com/yourprofile

Each item also has a Description field (displayed as tooltip) and Google Conversion Tag (to track clicks via Google Ads).

Display options
Option Description
Show button Enable/disable the entire CTA area on the website.
Display type Icon — show icon only
Icon + Text — show icon with label
Combined Icon — grouped into a single button, click to expand the list
Position Left or Right of the screen.
Support title Label displayed above the button group (when display type is Combined Icon). Example: "Contact us".
This setting supports multilingual — you can set separate content for each language via the language selector on the settings page.
Two-Factor Authentication (2FA) Settings

Enable two-step authentication using Google Authenticator for all admin accounts. When enabled, each login requires the admin to enter an OTP code from the Google Authenticator app on their device.

Navigate to: Admin Settings Two-Factor Authentication (2FA) Open page
Settings
Field Description
Enable 2FA Toggle to enable/disable the two-step authentication requirement for all admins. Applies to all accounts simultaneously.
How to set up for each admin account
  1. Enable the "Enable 2FA" toggle on this page and save.
  2. Each admin goes to Account Information → scans the QR code using the Google Authenticator app (iOS / Android).
  3. Enter the 6-digit OTP code from the app to confirm the link.
  4. From the next login, the system requires entering the OTP after the correct username and password have been entered.
If an admin loses the device linked to 2FA, a super admin must reset the secret key in the database or temporarily disable 2FA to allow login again. There is no automatic recovery via email.
All admin routes pass through the 2fa middleware. When 2FA is enabled and the admin has not verified the OTP in the current session, they will be redirected to the OTP entry page before accessing the admin panel.
Ads.txt Settings Settings

Manage the content of the ads.txt file — the authorized seller verification file per IAB standards. Required when running Google AdSense, Google Ad Manager or other advertising networks.

Navigate to: Admin Settings Ads.txt Open page
Edit content

Paste the content of the ads.txt file into the textarea. Each line is a seller declaration, following the standard:

google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0
advertising.com, 12345, RESELLER

The content is saved to the physical file at public/ads.txt. Leave blank to delete the file.

To get the exact ads.txt content for Google AdSense: log into AdSense → Account → Access & Authorization → Ads.txt → copy the declaration and paste it here.
The file is served at /ads.txt. Ad networks will automatically crawl this URL to verify. Check after saving by opening that URL in a browser.
Tracking — Conversion Tracking Settings

Configure conversion tracking codes (Google Ads Conversion, Facebook Pixel...) for key booking events: initiate booking, appointment confirmed, payment successful.

Navigate to: Admin Settings Tracking Open page
Architecture — Hook-based

The Tracking page has no hardcoded content — all tabs and forms are injected by other modules via the filter hook FILTER_LIST_DATA_GOOGLE_CONVERSION. Each module registers its own group of tabs.

If no module has registered yet, the page displays the message: "This feature is only available for service booking platforms!"

Service Booking Tracking — 3 main events

The Service Booking module injects tracking tabs via renderGoogleConversionSetting():

Tab / Event When triggered
Initiate booking When a customer starts the booking flow — selects a service or branch.
Appointment confirmed When the booking form is submitted and an appointment is created successfully.
Payment successful When the customer completes online payment for an appointment — runs on the thank-you page.
Tracking code configuration

Each tab has the following fields:

Field Description
Activate Enable/disable this tracking event.
Page load code Script that runs when the event page loads. Paste code from Google Ads, GTM event or Pixel.
Conversion code (on click) Script that runs when the button is clicked. Supports dynamic parameters.
Dynamic parameters The system replaces parameters in the code before rendering:
{price_total} — Total order value
{currency} — Currency unit
{transaction_id} — Order ID
To track with Google Ads: create a Conversion Action in Google Ads, get the script gtag('event', 'conversion', {...}) and paste it into the Conversion code field of the corresponding event. Use the {price_total} parameter for the conversion value.
Automatic Table of Contents (TOC) Settings

Automatically generate and insert a Table of Contents (TOC) into post, single page and product content based on heading tags (H2, H3...) found in the content.

Navigate to: Admin Settings Table of Contents (TOC) Open page
Configuration options
Field Type Description
Enable / Disable TOC toggle Enable to activate the feature. When disabled, the TOC will not appear anywhere on the website.
Display position select Before first heading — insert TOC just before the first H2/H3
After first heading — insert after the first heading
Before content — insert at the top of all content
After content — insert at the bottom of content
Display modules checkbox Select which modules will apply TOC:
Posts — post detail page (Post)
Single Pages — Page
Products — service detail page (Booking)
Multiple modules can be selected at once.
How it works

When TOC is enabled, the system analyzes the HTML of the content field (CKEditor), finds all <h2>, <h3>, <h4>... tags, assigns id attributes to each heading, then generates a TOC HTML block and inserts it at the selected position.

The TOC is only generated if the content has 2 or more headings. If there is only 1 heading, TOC will not be displayed.

Settings are saved with setting_name = 'cms_toc'. The post and product modules automatically read this config to decide whether to show TOC or not — no need to add shortcodes or code to templates.
Currency Settings Settings

Manage supported currencies, configure price display formatting and options for auto-detecting currency based on visitor location.

Navigate to: Admin Settings Currency Open page
Display configuration
Field Description
Default currency symbol String displayed before/after the price. Example: , đ, VND.
Auto-detect currency Enable to have the system automatically switch to the appropriate currency based on the visitor's IP geolocation. Requires multiple currencies to be configured.
Space between price and symbol Enable to add a space between the price number and the currency symbol. Example: 100,000 đ instead of 100,000đ.
Thousands separator , (comma), . (period), or space. Example: 1,000,000 or 1.000.000.
Decimal separator . (period) or , (comma). Example: 99.99 or 99,99.
Currency list management

The lower section of the page allows adding/editing/deleting currencies. Each currency includes:

Field Description
Name Currency name. Example: Vietnamese Dong.
Code ISO 4217 code. Example: VND, USD.
Symbol Display symbol. Example: , $.
Exchange rate Exchange rate relative to the default currency. The default currency is set to 1.
Default Mark as the default currency displayed to visitors. Only one currency can be set as default.
There must be at least one currency. You cannot delete all currencies — the system will show an error if the list is empty after saving.
Language Settings Settings

Manage supported languages on the website, configure the default language, enable multilingual mode and set the system timezone.

Navigate to: Admin Settings Language Open page
Language list management

The Language tab (default) allows adding, editing, deleting and enabling/disabling languages. Each language includes:

Field Description
Select language Dropdown to select from a standard language list. When selected, the system auto-fills Name, Locale, Code and Text direction.
Name Display name of the language. Example: Vietnamese, English.
Locale Locale code used for translation directories. Example: vi, en_US.
Language code ISO code (2 characters). Example: vi, en. Used in query strings when switching language.
Text direction LTR (left to right — default) or RTL (right to left — Arabic, Hebrew).
Country flag Flag icon displayed in the language switcher on the frontend.
Sort order Display order in the list. Lower numbers appear first.
The first language added will automatically be set as default. When adding a new language, the system automatically creates a translation directory at lang/{locale}/ by copying from lang/en/.
Language settings (Settings tab)

Configuration saved with setting_name = 'siteLanguage'. Contains 4 fields:

Field Type Description
Default language select Default display language for website visitors. Must be selected from the list of Active languages. Default: vi.
Admin panel language select Language displayed in the admin interface (admin panel). Separate from the frontend language. Default: vi.
Enable multilingual toggle Enable to allow visitors to choose their language. When enabled, the Language Switcher appears on the frontend. When disabled, the website uses only the default language.
Timezone select Timezone used for the entire system — post publish times, orders, logs... Default: Asia/Ho_Chi_Minh (UTC+7).
Language Switcher

When multilingual is enabled, visitors can switch languages via the query string ?lang={code}. The system uses LanguageNegotiator to determine the current language by priority order: query string → cookie → Accept-Language header → default language.

Member Settings User

Configure social login (Google OAuth) and policy links displayed in the registration form. All settings are saved to the settings table with setting_name = 'setting_auth_social'.

Navigate to: Admin Settings Member Settings Open page
Google OAuth Login

Allows users to log in quickly using their Google account instead of creating a separate password. You need to create an OAuth application at Google Cloud Console to obtain the credentials to fill in here.

Field Required Description
Google Client ID auth_social_google_client_id No Application identifier issued by Google. Format: 123456789-xxxx.apps.googleusercontent.com. Obtain from Google Cloud Console → APIs & Services → Credentials.
Google Client Secret auth_social_google_client_secret No Secret password corresponding to the Client ID. Do not expose or commit to code.
Guide to obtaining Client ID & Secret: go to Google Cloud Console → select project → APIs & Services → Credentials → Create credentials → OAuth 2.0 Client ID → select type Web application. Add the callback URL https://yoursite.com/auth/google/callback to the Authorized redirect URIs field.
Policy links in registration form

When users register an account, the form displays the sentence: "By checking and proceeding to register, you agree with us regarding..." along with links to policy pages. Each field below allows selecting a single page already created in the Page module — the system will automatically use that page's URL to create the link.

Field Required Description
Privacy policy page policy_page_id No Page describing how the website collects and uses users' personal information. Displays as "privacy policy" link in the registration form.
General policy page policy_general_page_id No Page outlining general policies when using the service (rules, return policy, etc.).
Terms of service page term_page_id No Page presenting the terms and conditions users must accept when registering an account.
Complaint handling mechanism page complaint_handling_mechanism_page_id No Page guiding users on how to submit complaints about personal data handling (often required by digital service legal regulations).
Support page support_page_id No Contact or customer support page. Displays as "support" link at the end of the terms confirmation sentence.
All fields are optional. If a field is left blank, the corresponding link will not appear in the registration form on the frontend. This setting is shared across all languages (hasLocale = false) — no need to reconfigure per locale.
Contact Management System

Store and track all contact requests from website users — including regular contact forms and newsletter subscriptions. Admins can view content and mark processing status.

Navigate to: Admin Contacts Open page
Filters
Filter field Description
Email Search by sender's email address.
Subject Search by contact subject / title.
Status New (0) — unread, displayed prominently
Contacted (1) — opened and viewed or manually marked
Type contact — contact request from the contact form
newsletter — email newsletter subscription
Time Filter by date range submitted.
Table information
Column Description
Email Sender's email address.
Full name Sender's name (if provided).
Phone number Sender's phone number (if provided).
Subject Contact subject / title.
Status Can be changed quickly directly in the table (quick edit) without opening the detail view.
Time Date and time the request was sent.
View contact details

Click the View icon to open the detail page. At that point:

  • If the contact is in the New status, the system automatically changes it to Contacted.
  • Displays the full message content, contact information, and the URL of the form submission page.
Contact data is read-only — cannot be created or edited manually from the admin. The bulk add/edit/delete and trash features are not enabled for this module.
System Logs System

Records all admin actions across the system: create, update, delete, login. Allows searching and restoring permanently deleted data.

Access: Admin System Logs Open Page
Filters
Filter Field Description
Admin Filter by the admin performing the action.
Module Type Filter by the affected table/module (posts, products, orders...).
Record Name Search by the specific name of the affected item (LIKE).
Action Filter by the type of action (see table below).
Time Filter by the time range.
Recorded Actions
Action Description
create Admin creates a new record.
update Admin updates the content of a record.
quick_update Quick update from the list table (change status, quick edit).
quick_delete Move the record to the trash.
quick_restore Restore the record from the trash.
delete_forever Permanently delete from the trash. This type of log allows rollback of data.
login Admin logs into the system.
Information in the table
Column Description
Admin The account name that performed the action.
IP The IP address of the device at the time of the action.
Action The type of operation (create / update / delete_forever...).
Module The affected table/module (posts, products, orders...).
Time The exact time the action was performed.
Rollback — Restore Deleted Data

When an admin permanently deletes a record, the system saves all old data (including slug, language, SEO, related comments) into the log with the action delete_forever.

To restore, open the log detail page and click "Rollback":

  1. The system recreates the record in the original table with the old data.
  2. Restores with slug, language_metas, meta_seo and comments if any.
  3. Removes the log from the list (to avoid duplicate rollbacks).
  4. Redirects to the edit page of the restored record.
Rollback is only available for logs with the action delete_forever. Logs of other actions (create, update...) are for reference only and do not support rollback.
Delete Logs in Bulk

Use the "Delete Logs" button on the list page (visible if you have the system_logs_delete permission) to delete the filtered logs. This action cannot be undone — the rollback data of the deleted logs will also be lost.

It is recommended to check logs regularly to monitor suspicious activities. Filter by Admin + Action = delete_forever to quickly find recent deletions that can still be rolled back.
Payment List Payment

View all payment transactions from booking orders. Supports filtering by transaction ID, method, and status.

Access: Admin Payment Open Page
Search Filters
Filter Field Description
Transaction ID Search by charge_id — transaction ID from the payment gateway.
Payment Method Filter by gateway: COD, Bank Transfer, VNPay, PayPal, Stripe... The list is automatically extended when additional payment packages are installed.
Status Pending — new transaction, not yet confirmed
Success — payment completed
Failed — transaction rejected / error
Refunded — refunded to customer
Columns in the table
Column Description
Transaction ID Transaction ID from the payment gateway. Click to view details.
Payer Information Name and information of the customer associated with the order.
Amount Transaction value, displayed with currency unit.
Payment Method Payment gateway used.
Status Badge color indicating the current status. Can be updated manually on the detail page.
Time Transaction creation time.
Payment page does not have Add New or Trash — transactions are only created automatically when a customer places an order. Each page displays 30 records, sorted with the newest first.
Transaction Details Payment

View full information of a payment transaction, manually update the status, and view refund information from the payment gateway.

Display Information

The detail page consists of two parts: basic information (from the payments table) and extended information (injected from the corresponding payment package via the filter PAYMENT_FILTER_PAYMENT_INFO_DETAIL).

Field Description
Transaction ID (charge_id) Original transaction ID from the gateway. Used to look up on the payment gateway dashboard.
Amount Payment amount.
Method Payment method used.
Status Dropdown allows manual update. The Pending status is hidden if the transaction is already processed.
Payment Gateway Information Extensions inject details for each gateway — for example, VNPay shows bank code, response code; PayPal shows payer email, PayPal transaction ID.
Refund If the gateway supports it (VNPay), there is a button to view refund information. Clicking it opens a popup where you can view detailed information of each refund attempt, including time and amount. The data is taken from the field metadata.refunds[].
Extension Architecture

Package payment con (VNPay, PayPal, Stripe...) inject detailed content into this page via the filter PAYMENT_FILTER_PAYMENT_INFO_DETAIL. Each package returns its own HTML from its view, for example Vnpay::detail or DreamTeamPayPal::detail. If the package is not installed, this section is empty.

Payment Methods Settings

Enable/disable and configure each payment gateway. Includes built-in methods (COD, Bank Transfer) and extensions injected via hooks.

Access: Admin Payment Payment Methods Open Page
Payment Methods List

This page displays a table of all payment methods. Each method has a status badge (Enabled/Disabled) and a Settings button to access its configuration page. If it is the default method, a "Default" badge will be displayed.

Payment Method Description
COD Cash on Delivery. Pre-installed in PaymentMethodEnum::COD, no API key required. Setting key: payment_cod_status.
Bank Transfer Displays bank account information for customers to manually transfer funds. Setting key: payment_bank_transfer_status.
VNPay Vietnamese domestic payment gateway. Injected via hook PAYMENT_METHODS_SETTINGS_PAGE from package payment-vnpay. Supports refunds.
PayPal International payment gateway. Injected from package payment-paypal. Automatically converts to USD if the currency is not supported.
Stripe International payment gateway. Injected from package payment-stripe.
Configure Each Payment Method

Each payment method has its own configuration page. The form content is injected via the filter PAYMENT_METHODS_SETTINGS_RENDER_PAGE. Common fields include:

Field Applicable to
Set as Default All. Setting key: default_payment_method. Once enabled, the payment method name will be saved to this key.
Display Name / Description COD, Bank Transfer, VNPay, PayPal, Stripe — hiển thị trên trang checkout.
Client ID / Client Secret PayPal: payment_paypal_client_id, payment_paypal_client_secret.
VNPay: payment_vnpay_client_id (TmnCode), payment_vnpay_client_secret (HashSecret).
Secret Key / Publishable Key Stripe: payment_stripe_secret, payment_stripe_publishable.
Bank Account Information Bank Transfer: bank name, account number, account holder, QR code for transfer.
Hook-Based Architecture

Extension gateways (VNPay, PayPal, Stripe) register into the payment system through 3 main hooks:

Hook Purpose
PAYMENT_METHODS_SETTINGS_PAGE Add a row to the payment methods list table.
PAYMENT_METHODS_SETTINGS_RENDER_PAGE Render configuration form when accessing the settings page of that payment method.
PAYMENT_FILTER_AFTER_POST_CHECKOUT Handle payment logic (create redirect link, call gateway API) when a customer places an order.
PAYMENT_FILTER_PAYMENT_INFO_DETAIL Inject HTML transaction details into the payment detail page in the admin panel.
To add a new payment gateway: create a package following the structure HookServiceProvider and register the above filters. No need to modify the core payment package. The system will automatically detect and display the new gateway in the list.
Admin Account Management Administration

Create and manage admin accounts. Each account can be assigned roles, detailed permissions, avatars, and author information.

Access: Admin Admin Management Open Page
Filters
Field Description
Name Search by username (slug).
Email Search by email.
Role Filter by created role groups.
Creation Date Account creation date range.
Status Active / Inactive / Draft.
Add New Account

Two-column form: the left side is account information, the right side is permissions.

Field Required Description
Username Yes Username used for login. Automatically converted to slug. Maximum 191 characters.
Email Yes Login email, must be unique.
Password / Confirm Yes Password is hashed using bcrypt. Supports random password generation button.
Avatar No Avatar image. Displayed in the post list and author page on the frontend.
Display Name No Display name on the frontend (different from username).
Position No Displayed under the author's name on the post page.
Author Bio No Short description (up to 200 characters). Displayed in the author box under the post.
Social links No Website, Facebook, Twitter, Pinterest, Instagram, YouTube — stored as JSON in the social column.
Full Author Bio No CKEditor content for the full author page.
Role No Select either a predefined role with specific permissions, such as Super Admin (full access) or a custom role. When selecting Super Admin, is_supper_admin = 1, there is no need to select detailed permissions.
Custom Permissions No Override role permissions. Stored as JSON in the capabilities column.
When enabling Two-Factor Authentication (2FA) in Security Settings, the admin list will display an additional column "2FA" indicating whether the account has activated Google Authenticator.
Roles & Permissions Admin

Create and manage role groups. Each role defines a set of permissions allowed to perform in the admin panel.

Access: Admin Admin Roles Open Page
Role Structure

The system has 2 levels of permissions:

Type Description
Super Admin Account with is_supper_admin = 1. Full access, not checked for permissions. Can be selected directly when creating/editing an admin user.
Custom Role Role group created on this page. Stores the list of permissions in JSON format in the permissions column. When an account is assigned a role, it will only have access to the allowed functions.
Add / Edit Role
Field Required Description
Role Name Yes Display name. For example: Editor, Accountant.
Permission List Yes Permission checklist by module (posts, appointments, services, settings, etc.). Each module typically includes the following permissions: view, add, edit, delete, deleteForever.
Status Required Roles with Inactive status will not appear in the role selection dropdown when creating a new admin user.
Changes to a role's permissions take effect immediately for all accounts assigned to that role — users do not need to log out and log back in.
Comment Management Comment

Review, edit, reply to, and delete customer comments. Comments can come from multiple modules: posts, products, static pages, etc.

Access: Admin Comments Open Page
Filters
Field Description
Name Search by commenter name.
Content Full-text search within comment content.
Comment Date Comment creation date range.
Display Status Visible — comment is publicly displayed on the frontend. Hidden — comment is hidden.
Processing Status Processed (admin has replied/approved). Unprocessed — requires attention.
Comment Actions
Action Description
Edit Comment Admin can modify customer comment content. For product comments, attached images can also be edited.
Quick Reply Admin replies directly from the list. The reply is created as a child comment (parent_id) with admin_id assigned. Status is automatically set to Visible.
Hide Comment Change status to Hidden — the comment will not appear on the frontend but is not deleted.
Permanently Delete Completely remove from the database. When a parent comment is deleted, all child comments (parent_id) are deleted as well. The action is recorded in the System Log.
Comment Type (type)

The type column identifies which module the comment belongs to. Examples: posts, products, pages. Hidden filters type and type_id allow filtering comments by a specific post/product when opened from the content detail page.

The comment feature for blog posts can be completely disabled in Post Settings → Allow Comments (BlogHelper::isCommentEnabled()). When disabled, the comment form is completely hidden even though the Comment module remains active.
Location Management Location

Manage 3-level geographical data: Country → Province/City → District → Ward. This data is used in address forms and branch location display.

3-Level Geographic Structure
Level Route Description
Country admin.countries.* Highest level. Examples: Vietnam, USA. Each province/city belongs to a country.
Province/City admin.provinces.* Provincial/city level. Can be filtered by country. Deleting a province automatically deletes all child wards.
Ward admin.wards.* Lowest level, belonging to a province/city.
Bulk Import / Export

The module supports importing geographic data from Excel files via BulkImportController. Used when importing complete province/district/ward data for a new country.

Action Description
Import Excel Upload an .xlsx file with the structure: location name, code, parent ID. The system automatically creates all records.
Export Excel Export all province/ward data to an Excel file. Used for backup or migration to another environment.
Each location automatically generates a code from its name (uppercase slug). This code is used for lookup or synchronization with external systems. Multi-language support is available — each location name can be translated by locale.