Skip to main content

Google Calendar Sync

WooCommerce Appointments syncs with Google Calendar so store appointments appear in Google, and busy Google events can block booking slots.

Before you begin

How it works

Google Calendar sync bridges your store and a Google calendar. Appointments push to Google when connected. In two-way mode, future Busy events on that calendar import as availability blocks so customers cannot double-book.

What you need

  • A live site with HTTPS (not localhost or plain HTTP)
  • A Google account (Gmail or Google Workspace)
  • Pretty permalinks — any structure except Plain (required for REST API and OAuth; see Developers)
  • Time (first-time setup): ~20–30 minutes in Google Cloud (Part A) + ~15 minutes in the plugin (Part B). Faster if you have done Google OAuth before — see Quick start below.

What syncs

  1. ✅ Appointments created or updated in WooCommerce → appear/update in Google Calendar
  2. ✅ Appointment changes in WooCommerce → update Google Calendar

Two-way only (Sync Preference → Two way)

  1. ✅ Future Google events marked Busy → block availability in WooCommerce
  2. ✅ Future Google event changes → can update linked appointments
  3. ✅ Future Google event deletions → can cancel linked appointments

What does not sync

  1. ❌ Google events marked Free or Available — only Busy blocks time
  2. ❌ Past Google events inbound (future window only, up to ~1 year)
  3. ❌ Google events on the WooCommerce admin calendar — they block slots only; they are not shown as appointment cards

Important

  • Each staff member connects one calendar with their own OAuth token (Part C)
  • Disconnecting the store calendar does not disconnect staff
  • Outbound sync uses the site timezone — match Google Calendar for predictable times (Timezones)
  • Re-sync from Google Calendar and inbound blocking require two-way sync and a Calendar ID selected
Quick start (if you've set up Google OAuth before)
  1. Google Cloud: new project → enable Google Calendar API

  2. OAuth consent: External or Internal → add scope https://www.googleapis.com/auth/calendar only (not read-only or events-only)

  3. Credentials: OAuth client ID → Web application → authorized redirect URI:

    https://YOUR-DOMAIN/wc-api/wc_appointments_oauth_redirect
  4. Plugin: WooCommerce → Settings → Appointments → Google Calendar → paste Client ID and Secret → Save changesContinue with Google → select Calendar IDSync Preference

For External apps in Testing, add each connecting Google account as a test user, or Publish the app for production.

Full walkthrough with screenshots: Part A · Part B

Setup order: Part A — Google CloudPart B — Store settingsPart C — Staff calendars (optional)

Part A — Google Cloud Console

Create OAuth credentials that your WordPress site uses to access the Calendar API.

Console navigation

Google may label this APIs & Services → OAuth consent screen or Google Auth platform. Menus change over time; match the step names below to the closest screen in your console.

A1. Create a project

  1. Open Google Cloud Console.
  2. Click the project picker (top bar) or press Ctrl+O.
  3. Click NEW PROJECT.

Left: Project picker with NEW PROJECT

Google Cloud project picker — verify NEW PROJECT is visible

Right: New project name dialog

New project form — enter project name and CREATE
  1. Enter a project name (e.g. WooCommerce Appointments) and click CREATE.
  2. Select the new project from the picker when creation finishes.

A2. Enable Google Calendar API

  1. Open the menu (☰) → APIs & Services → Library.
  2. Search for Google Calendar API.

Search API Library for Google Calendar API

  1. Open Google Calendar API and click Enable.

Enable Google Calendar API

The consent screen is what users see when they click Continue with Google in WordPress.

  1. Go to APIs & Services → OAuth consent screen (or Google Auth platform).

Open OAuth consent configuration

  1. User type

    • External — public sites; add test users while in Testing mode
    • Internal — Google Workspace only; no test users required

    Click CREATE.

Choose External or Internal user type

  1. App information — app name and user support email:

OAuth app information step

  1. Contact information — developer contact email(s):

OAuth developer contact emails

  1. Branding (logo, app domain) — complete if shown, then Save and continue:

OAuth branding step

  1. Data access (scopes)

    Click Add or remove scopes, search for calendar, and enable exactly one scope:

    Scope URLGoogle Console label (may vary)
    https://www.googleapis.com/auth/calendarSee, edit, share, and permanently delete all the calendars you can access using Google Calendar

    Save the scope list.

    Minimum required — one scope only

    WooCommerce Appointments requests this single scope during Continue with Google. Add only …/auth/calendar on the consent screen. You do not need Gmail, Drive, Contacts, or other Google APIs.

    What the plugin uses this scope for

    FeatureGoogle Calendar APISync mode
    Populate the Calendar ID dropdown after connectcalendarList (list calendars)One-way and two-way
    Push appointments to Google (create / update)events.insert, events.updateOne-way and two-way
    Remove Google events when appointments are cancelledevents.deleteOne-way and two-way
    Import busy Google events as availability rulesevents.list (including syncToken incremental sync)Two-way only
    Match recurring or edited Google eventsevents.getTwo-way only

    Scopes you do not need

    • …/auth/calendar.readonly — read-only; cannot create or update events (outbound sync would fail)
    • …/auth/calendar.events or …/auth/calendar.events.readonly — the plugin also calls calendarList; these narrower scopes are not what OAuth requests
    • …/auth/calendar.settings.readonly — Calendar settings are not used
    • Any non-Calendar scope (Gmail, Drive, etc.)
    Match the plugin scope exactly

    OAuth is built for https://www.googleapis.com/auth/calendar only. If the consent screen lists different scopes, authorization can fail or the Calendar ID list may stay empty. Do not substitute read-only or events-only scopes unless you customize the plugin via the wc_appointments_gcal_oauth_auth_params filter (developer customization).

Calendar API scope checked on Data access step

  1. Test users (External apps in Testing only)

    Add each Google account that will connect during development.

Add OAuth test users

  1. Summary — review and return to the dashboard.

OAuth consent summary — Back to dashboard

External apps in Testing

While status is Testing, only listed test users can authorize. Tokens may expire after about 7 days, causing frequent re-auth. For production, publish the app (A5).

A4. Create OAuth client ID

  1. APIs & Services → Credentials+ Create credentialsOAuth client ID.

Create credentials menu

  1. Application type: Web applicationCreate.

Select Web application type

  1. Configure the client:

    • Name: e.g. WooCommerce Appointments

    • Authorized redirect URIs — add exactly (replace domain):

      https://your-site.example.com/wc-api/wc_appointments_oauth_redirect
    • Authorized JavaScript origins — leave empty unless Google support advises otherwise

Redirect URI filled with your site domain

  1. Click Create and copy Client ID and Client secret immediately.

OAuth client created — copy ID and secret

warning

The client secret is shown only once. Store both values securely before closing the dialog.

A5. Publish the app (production)

For External apps used by customers or staff beyond test users:

  1. OAuth consent screenPublishing status.
  2. Click Publish app and confirm.

Publish OAuth app to production

StatusTypical symptom
TestingOnly test users can connect; tokens may expire ~weekly
In productionAny Google user can authorize; stable long-lived refresh tokens

Part B — Store settings

WooCommerce → Settings → Appointments → Google Calendar

B1. Client ID and secret

  1. Paste Client ID and Client Secret from A4.
  2. Click Save changes.

Disconnected — credentials entered, not yet authorized

Fields are stored as masked password inputs.

B2. Authorize (Continue with Google)

After saving credentials, click Continue with Google (Google Identity branding).

  1. Sign in and grant calendar access in the popup.
  2. On success, the page shows Successfully authenticated.

Connected — authenticated with Disconnect button

Disconnect clears store tokens and cached access data. It does not disconnect staff calendars.

Two-way disconnect

If two-way sync imported Google events as synced rules, disconnecting the store does not remove them. Export or use Backup & Restore before a full re-sync if you need to roll back.

B3. Calendar ID

After authorization, choose a Calendar ID from the dropdown (or enter manually if the list is empty).

  • Leave N/A / empty for staff-only sync — no global inbound rules, but staff can still connect their own calendars
  • Required for Re-sync from Google Calendar and global two-way import

Save changes after selecting a calendar.

B4. Sync Preference

Visible only after OAuth is connected.

OptionBehavior
One way — from Store to GoogleAppointments push to Google; Google events do not block store availability
Two way — between Store and GoogleAppointments push to Google and busy Google events import as synced availability rules

Two-way sync with calendar selected

B5. Re-sync from Google Calendar

Shown only when all of the following are true:

  • Store is connected (refresh token saved)
  • A Calendar ID is selected
  • Sync Preference is Two way

Click Re-sync from Google Calendar for a full import of busy events into synced rules. A confirmation explains that existing synced rules are replaced and a backup is created automatically.

Progress appears in a bar during chunked processing:

Re-sync progress bar

Scheduled sync runs automatically in the background. It picks up new and changed busy events going forward.

Re-sync from Google Calendar does a full import of busy events into synced rules. Use it after bulk Google Calendar changes, or when you need to refresh older events that scheduled sync has not touched yet.

B6. Backup & Restore

In the Backup & Restore section (two-way sync enabled and a calendar selected):

ActionPurpose
Export Rules (JSON)Download current synced rules
Import RulesRestore from a JSON export
View BackupsList auto-backups created before re-sync

Backup and Restore section expanded

  • Up to 5 backups retained; entries older than 7 days are pruned
  • Restoring replaces synced rules without pushing changes back to Google

B7. Debug log

Testing section (separate from sync controls):

  • Enable Debug Log to record API activity
  • Log file path is shown on the settings screen (under woocommerce/logs/)

Testing section with Debug Log enabled

Enable only while troubleshooting; disable in production.

B8. Token refresh

Access tokens refresh automatically (default: about every 50 minutes) via Action Scheduler. Adjust interval:

add_filter( 'woocommerce_appointments_gcal_token_refresh_interval', function () {
return 30 * MINUTE_IN_SECONDS;
} );

If sync stops with auth errors, try DisconnectContinue with Google again, or publish the OAuth app if still in Testing.


Part C — Staff calendars

Staff connect personal Google accounts. They do not inherit the store OAuth session or calendar list.

C1. Prerequisites

  1. Store Client ID and Client Secret saved (Part B1).
  2. Staff user has the Shop Staff role (or wc_appointment_staff where applicable).

C2. Where to connect

WhoPath
Staff (self)Staff Portal → Profile → Google Calendar
AdminUsers → edit staff user → Staff Profile → Google Calendar

Requires Staff Portal or admin user edit access.

C3. Per-staff calendar and sync mode

  1. Click Continue with Google and authorize.
  2. Select Calendar from the staff member's Google account.
  3. Choose Sync Mode:
    • One-way (Appointments → Google) — appointments appear on their calendar only
    • Two-way sync — their busy Google events block their assigned slots
  4. Connected status and Disconnect appear when linked.

Staff profile — calendar, sync mode, connected status

Staff Synced Rules appear under My Rules / Synced Rules on the profile (read-only). Global synced rules appear under Settings → Appointments → Global Availability.

Disconnecting a staff calendar clears local tokens only; it does not revoke the app at Google.


How sync behaves

Where to add code

Add filters in your child theme's functions.php or a small site-specific plugin — not in the plugin files (updates will overwrite them). See Where to add code.

Appointment statuses (store → Google)

By default, appointments sync when status is confirmed, paid, or complete. Extend with:

add_filter( 'woocommerce_appointments_gcal_sync_statuses', function ( $statuses ) {
$statuses[] = 'unpaid';
return $statuses;
} );

See Sync unpaid appointments to Google Calendar → Customization recipes (license required).

Synced rules (Google → store, two-way)

  • Imported rules are read-only in WordPress (except priority and title on some rows)
  • Edit or delete the event in Google Calendar, then re-sync or wait for scheduled sync
  • Scheduled inbound sync is forward-only — it does not re-import your entire Google history on every run
  • Default priority for synced events is 5 (manual rules default 10)

Details: Availability Rules — Synced rules.

Direction summary

EntityOne-wayTwo-way
New WooCommerce appointment→ Google event→ Google event
Updated appointment→ Updates Google→ Updates Google
Busy Google event→ Blocks availability (synced rule)
Future Google event edit/delete→ May update/cancel linked appointment
Free Google eventIgnored

Troubleshooting

SymptomCheck
Redirect URI mismatchRedirect URI in Google Cloud must match exactly: https://YOUR-DOMAIN/wc-api/wc_appointments_oauth_redirect
404 on OAuth callbackPermalinks — use Post name (or any non-Plain structure) and save. See Permalinks settings screenshot
Access blocked / app not verifiedExternal app: add user as Test user, or Publish the app
Re-auth every ~7 daysApp still in Testing — publish to production
Continue with Google missingSave Client ID and Secret first
Sync Preference hiddenComplete OAuth first
Re-sync button missingSelect Calendar ID and set Sync Preference to Two way
Events not blocking slotsEvent must be Busy; two-way must be enabled; allow time for sync
Wrong times in GoogleAlign site timezone with Google Calendar timezone
Calendar list empty after connectDisconnect and reconnect; check API is enabled; review debug log
404 on calendar fetchPlugin clears token — re-select calendar after reconnect
Synced rules missing after site cloneInbound sync skips events tied to another site URL — run Re-sync from Google Calendar on the live site

Enable Debug Log (B7) and reproduce the issue before contacting support.