Widget Reference Guide
Everything you need to embed, configure, and customize your Planning Center calendar widget.
Product Overview
PCOWidget is a self-contained, embeddable calendar that pulls live event data from your Planning Center Online calendar and renders it as an interactive, styled component on any web page — with a single <script> tag.
sermon: Your Title in PCO event notes — it surfaces automatically on service tiles.How It Works
PCOWidget sits between your church website and Planning Center. Your site never touches PCO credentials — they live encrypted on PCOWidget's servers.
Your Church Website (Squarespace, WordPress, Wix, HTML)
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY">
↓
api.pcowidget.com
↓
Your API key → your PCO credentials (encrypted, server-side)
↓
api.planningcenteronline.com/calendar/v2
↓
Events rendered as HTML → injected into your page
- Your
<script>tag loads the widget JavaScript from PCOWidget's API servers - The widget auto-detects its endpoint from its own
srcURL - PCOWidget's PHP middleware authenticates with Planning Center using your encrypted credentials (never exposed to visitors)
- Events are fetched, formatted, and returned as styled HTML
- Month navigation and view switching fetch lightweight HTML fragments — no full page reload
Embedding the Widget
Basic Embed
One line. That's it. Paste into any HTML page, Squarespace Code Block, or WordPress Custom HTML block:
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"></script>
Replace YOUR_KEY with the API key from your PCOWidget account dashboard. Your key is provisioned when you sign up.
Squarespace
Add a Code Block (not a Markdown block) and paste your script tag. No <html>, <head>, or <body> tags needed — the widget handles everything.
Cards layout width on Squarespace: Squarespace wraps code blocks in a .sqs-code-container element that can render as inline-block, preventing the card grid from filling the full column width. If your cards appear narrower than expected, add this to Design → Custom CSS:
.sqs-code-container {
display: block;
width: 100%;
}
WordPress
Add a Custom HTML block in the Gutenberg editor and paste the script tag.
Mounting Into an Existing Element
If you already have a container div where you want the widget, use data-target:
<div id="my-calendar"></div>
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-target="my-calendar"></script>
Multiple Instances on One Page
Each <script> tag creates an independent widget instance. Configure each with different data-* attributes:
<!-- Full church calendar -->
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="table"></script>
<!-- Youth events sidebar -->
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-tag="Youth"
data-layout="list"></script>
<!-- This week's services (homepage) -->
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="simple"
data-this-week="1"
data-title="This Week's Services"></script>
Data Attributes
Control each widget instance using data-* attributes on the <script> tag:
Boolean attributes accept multiple formats.
Any of "1", "true", "True", or "TRUE" are treated as on.
Any of "0", "false", "False", or "FALSE" are treated as off.
This applies to data-featured, data-this-week, data-allow-week-nav, data-include-past, data-hide-end-time, data-hide-if-empty, and data-include-unpublished.
Only approved, published events are shown.
The widget displays events that are approved in Planning Center and published to Church
Center. Unpublished events, and anything still pending or rejected in your approval workflow, stay
off your site. That is what you want for internal holds, tentative bookings, and staff-only items.
If an event is missing from your website, check its publish setting in Planning Center first. See
data-visibility below to build a staff-only preview widget that shows the levels
underneath.
Want to see every option in action? The live examples page shows all layouts, filters, and combinations running against real ELC data.
table
table · list · cards · tiles · week · simpletable = month grid, simple = service tiles, tiles = compact image grid, others as named. See Layouts for details.00 if you would rather visitors have to click a tile to open it. Tapping on a phone always opens it either way.data-tag="Youth,Women's Ministry" shows events tagged either Youth or Women's Ministry.true · 1simple layout.true · 1simple layout so visitors can browse upcoming weeks. The prev button is disabled on the current week. The center label shows "This Week" / "Next Week" / "+N Weeks" and clicking it returns to the current week.center
left · center · rightdata-title="This Week's Services" or data-title="Youth Events".2 on simple, auto on cards
1 – 8simple layout this always applies and defaults to 2. On the cards layout it is optional: set it to pin an exact number of columns, or leave it off and the cards fit themselves to the width of whatever you dropped the widget into. Pinned counts above 2 step down to 2 columns on tablets, and everything collapses to 1 column on screens ≤480px.true · 1 · false · 0true/1 = featured events only; false/0 = non-featured events only. Featured events get star indicators and accent borders on card layouts.no limit
1 – 250no limit
1 – 100data-columns, so data-rows="2" alongside data-columns="3" shows six events. The table and week layouts ignore this, because their rows are calendar weeks rather than events.blue
blue · burgundy · standardfalse
true · false · 1 · 0true for archive or recap pages where past events should remain visible.true · 1true · 1data-empty-message="Nothing scheduled this month. See our weekly service times below." Ignored when data-hide-if-empty is set, since nothing renders at all in that case.0Entries match either a tag group name or an individual tag name. Matching a group is usually what you want:
data-show-tags="Campus" shows every tag in
your Campus group and hides the rest, and a campus you add later appears automatically with no
change to your embed code. Use data-show-tags="0" to hide tag chips entirely.
This is display-only. It does not change which events appear. To filter events by tag, use
data-tag. The two can be combined: filter with data-tag, then tidy
the chips with data-show-tags.
1–6 (number of months to look ahead), or true for 1This solves the late-in-the-month problem: it is August 28th, the next event is September 3rd, and until now the widget showed an empty box.
data-auto-advance="2" is a sensible
starting point. Keep the number small: skipping five months ahead to surface one lonely event is
about as useful to a visitor as showing them last month's calendar.
Auto-advance applies only to the month the visitor first lands on. Once they click the month arrows, the month they asked for is shown exactly, empty or not, because silently skipping past it makes the arrows feel broken.
This is not an aggregate window. It picks which single month to show. If you want the next few months of events gathered into one set with no navigation, that is
data-months-ahead below.
Note: if you also use
data-hide-if-empty, auto-advance runs first.
The widget only disappears if no month within the lookahead window has events.
1–12 (months to gather)It is a rolling window from today, not a run of calendar months: on 26 August,
data-months-ahead="4" covers 26 August to 26 December. Finished events drop out
as they pass.
Pairs naturally with
data-tag and a data-rows or
data-limit cap, which is how you get a fixed-height strip of the soonest events
in a series.
Note: this replaces
data-this-week and
data-auto-advance rather than combining with them. All three choose a date
window, and this one has already chosen it.
Layouts:
list, cards, tiles and
simple. table and week draw a calendar grid whose rows
are the weeks of a single month, so they ignore it.
published · approved · pending · rejected| Level | What appears |
|---|---|
published | Approved and published to Church Center. The default, and the right setting for a public website. |
approved | Everything above, plus approved events you have not published yet. |
pending | Everything above, plus events still waiting on approval. |
rejected | Everything above, plus rejected events. In other words, your whole calendar. |
published as a staging or preview tool. Put a
second widget on a staff-only page with data-visibility="pending" and your team can
see what is coming through the approval queue and check how it will look, while the public page
keeps showing only finished, published events. Never set anything other than
published on a page your congregation or visitors can reach.
If your church does not use Planning Center's approval workflow at all, every event counts as approved and only the publish setting matters. Nothing changes for you.
true · 1data-visibility="approved": shows approved events whether or not you
have published them to Church Center. If you set both, data-visibility wins. Prefer
data-visibility in new embeds, since it says exactly how far you are going.
<div> element by ID. If omitted, the widget creates and inserts its own container after the script tag.Quick Reference Table
| Attribute | Values | Default |
|---|---|---|
data-layout | table · list · cards · tiles · week · simple | table |
data-hover-previewNew | 0 | on |
data-tag | tag name, or tag1,tag2 (OR) | — |
data-this-week | true · 1 | — |
data-allow-week-nav | true · 1 | — |
data-nav-align | left · center · right | center |
data-title | string | — |
data-columns | 1–8 | 2 simple / auto cards |
data-featured | true · 1 · false · 0 | — |
data-limit | 1–250 | no limit |
data-rowsNew | 1–100 | no limit |
data-shadow | blue · burgundy · standard | blue |
data-include-past | true · false · 1 · 0 | false |
data-hide-end-time | true · 1 | — |
data-hide-if-empty | true · 1 | — |
data-empty-messageNew | text, max 200 chars | "No upcoming events at this time." |
data-show-tagsNew | tag group name · tag name · list of either · 0 | show all tags |
data-auto-advanceNew | 1–6 (months to look ahead) | off |
data-months-aheadNew | 1–12 (months gathered from today) | off |
data-visibilityNew | published · approved · pending · rejected | published |
data-include-unpublished | true · 1 (shorthand for approved) | published only |
data-target | element ID | — |
Boolean Values — Accepted Formats
The five boolean attributes (data-featured, data-this-week,
data-allow-week-nav, data-include-past, and data-hide-end-time) are flexible about how
you write true or false. All of the following are valid:
| Meaning | Accepted values |
|---|---|
| On / true | "1" "true" "True" "TRUE" |
| Off / false | "0" "false" "False" "FALSE" (or omit the attribute entirely) |
Examples — these are all equivalent:
<!-- All three turn on data-this-week -->
<script src="..." data-this-week="1"></script>
<script src="..." data-this-week="true"></script>
<script src="..." data-this-week="TRUE"></script>
<!-- All three turn on data-include-past -->
<script src="..." data-include-past="true"></script>
<script src="..." data-include-past="True"></script>
<script src="..." data-include-past="1"></script>
Layouts
Choose from six layouts, each designed for a different use case:
Month Grid — data-layout="table"
Full monthly calendar grid (Sunday–Saturday). Shows day numbers with event indicators.
- Desktop: Event name and time visible inside grid cells
- Mobile (<768px): Colored dot indicators instead of event text
- Includes month/year header with prev/next month arrows and a view-switching toolbar
- Click any event to open the full-detail popover
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="table"></script>
Week Strip — data-layout="week"
Compact 7-day view extracted from the month grid. Shows only the row containing today (or the first row with events for non-current months). Ideal for sidebars or "this week" widgets.
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="week"></script>
List — data-layout="list"
Compact row-based layout with thumbnail images (or date badges when no image). Shows event name, date, time, and location. Stacks on mobile. Good for ministry landing pages with moderate detail.
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="list"
data-tag="Women's Ministry"></script>
Cards — data-layout="cards"
Rich card grid — auto-fit responsive layout. Each card is at least 260px wide; columns fill all available space naturally (typically 2 on tablet, 3+ on wide desktop, 1 on mobile). Each card shows:
- 16:9 image (or date badge placeholder)
- Date badge, title, time, description (3-line clamp), location
- Tag color badges
- "View Details" link
- Featured events get accent borders and star indicators
<!-- Featured events showcase -->
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="cards"
data-featured="1"
data-shadow="burgundy"></script>
Image Tiles New – data-layout="tiles"
A compact image grid that sits between simple (text only) and cards (large and detailed). Each tile is about a third the height of a card: the event's image, its name on up to two lines, and the date and time. Built for churches that want a dense, visual "what's on" block instead of a long scroll of full cards.
Choose your grid. data-columns sets how many tiles go across, from 1 to 8, and defaults to 4. data-rows sets how many rows deep it goes. Together they give you an exact block: data-columns="5" with data-rows="2" is always ten events, no matter how busy the month is. Leave data-rows off and it shows everything. On smaller screens the grid steps down to 3 across, then 2, so tiles never shrink into illegibility.
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="tiles"
data-columns="5"
data-rows="2"></script>
Events without a picture still look right. Not every event in Planning Center has artwork, and on some calendars most of them do not. Those tiles get a coloured panel with a small calendar icon rather than a blank or broken image. The colour comes from the event's name, so the same event always looks the same and the grid stays varied instead of repetitive.
Hovering opens the full event. Rest your pointer on a tile and the complete event card opens in the middle of the screen, with the large image, description, tags, location, and the "View Details", "Register", and "Add to Calendar" buttons. It waits for a brief pause before opening, so moving the mouse across the grid on the way somewhere else does not flash a card at you for every tile it passes over. Clicking or tapping opens it right away, and it works from the keyboard with Tab and Enter. Press Escape or click outside to close.
If you would rather visitors had to click, add data-hover-preview="0". Tapping on a phone opens the card either way, since phones have no hover.
Simple Tiles — data-layout="simple"
Minimal clickable service-time tiles. Each tile shows a clock icon, event name, sermon title (if set), date, and time range. Clicking a tile opens the full event popover. No toolbar — clean and focused.
Designed for use with data-this-week="1" to show the current week's events on your homepage or church info page.
Sermon Title Display
Your recurring "Traditional Worship" event stays the same in PCO, but the sermon title changes each week. To surface a sermon title on a simple tile, add a line to the PCO event's Details field:
sermon: Giving Expectantly
- The prefix (
sermon:) is stripped — only the title text is shown - The match is case-insensitive (
Sermon:,SERMON:, etc. all work) - The line can appear anywhere in the Details field
- If no
sermon:line is present, the subtitle is omitted — no blank space
Pro tip: The sermon title line can appear anywhere in the event Details field — beginning, end, or mixed with other content. Just make sure it's on its own line.
Week Navigation
Add data-allow-week-nav="1" to let visitors browse upcoming weeks. The prev button is disabled on the current week. The center label shows "This Week" / "Next Week" / "+N Weeks" and clicking it returns to today.
Column Count
Use data-columns to control tiles per row. If you have 4 services on Holy Week, set data-columns="4". Always collapses to 1 column on mobile. The same attribute now pins the cards layout too, and pairs with data-rows when you want a fixed block of events rather than the whole month.
<script src="https://api.pcowidget.com/v1/calendar-widget.js?key=YOUR_KEY"
data-layout="simple"
data-this-week="1"
data-title="This Week's Services"
data-tag="Worship Services"
data-allow-week-nav="1"
data-nav-align="center"
data-columns="2"></script>
Feature Flags
Feature flags are server-side controls managed by PCOWidget for your account. They determine which interactive features are enabled in your widget. All are enabled by default on Pro plans.
| Flag | Feature | Effect |
|---|---|---|
WIDGET_POPOVER |
Event popover | Click events to open a full-detail card (image, description, links, iCal) |
WIDGET_TRANSITIONS |
Slide transitions | Smooth left/right animation when navigating months |
WIDGET_ICAL |
iCal downloads | "Add to Calendar" links generate .ics files for Outlook, Google, Apple Calendar |
WIDGET_TAG_COLORS |
Tag color coding | Events colored by ministry category (see Tag Colors) |
WIDGET_THIS_WEEK |
Week view option | Enables the "Week" button in the toolbar; 7-day strip view |
To request a feature flag change for your account, get support through our contact form.
Shadow & Theming
Shadow Presets
Set the container shadow tone with data-shadow:
| Value | Visual | Best For |
|---|---|---|
blue |
Blue-tinted drop shadow | Default — works with most church sites |
burgundy |
Warm red/maroon tinted shadow | Traditional church aesthetics, warm palettes |
standard |
Neutral gray shadow | Minimal sites, any color scheme |
CSS Isolation
All widget CSS classes are prefixed with pcow-. Widget styles will not conflict with your site's existing CSS, even on Squarespace, WordPress, or Wix where host-site styles are aggressive.
Note: The widget deliberately avoids h1–h6 elements to prevent host-site heading styles from overriding widget typography.
Tag Colors
When tag color coding is enabled, events are automatically colored by their Planning Center tag. No configuration needed — the widget reads the tag name and applies the matching style.
Tags not in the default map receive the standard blue styling. Additional tag color mappings can be configured on your account — contact support to request custom tag colors.
Multiple tags: Events can have multiple PCO tags and all will be shown as color badges on card and list layouts. The data-tag attribute scopes which events are shown, not which tags are displayed. An event tagged "Youth" and "Outreach" shows both badges when you filter by data-tag="Youth".
Responsive Breakpoints
The widget is mobile-first and adapts at these breakpoints:
REST API Reference
The widget fetches data from PCOWidget's REST endpoint. You can call this directly for custom integrations or debugging.
Endpoint
GET https://api.pcowidget.com/v1/calendar-endpoint.php
Query Parameters
| Param | Values | Default | Description |
|---|---|---|---|
key | string | (required) | Your API key |
format | html · fragment · json | html | Response format |
layout | cards · list · table · tiles · simple | cards | Template layout (html/fragment only) |
month | YYYY-MM | (none) | Explicit month — auto-sets date range |
tag | PCO tag name | (none) | Filter by tag (case-insensitive) |
featured | 1 | (none) | Show only featured events |
limit | 1–50 | 10 | Maximum events returned |
after | YYYY-MM-DD | (none) | Date range start |
before | YYYY-MM-DD | (none) | Date range end |
filter | future · past | future | Time filter (suppressed when month is set) |
columns | 1–8 | 2 | Cards per row (simple layout only) |
Response Formats
format=html— Full HTML with wrapper div, scoped CSS, and feature flags JSON. Used for initial widget load.format=fragment— Layout HTML only (no wrapper, no CSS). Used by the widget for AJAX navigation.format=json— Raw JSON event data. Use for custom integrations or debugging.
Example Requests
# Test your key — returns JSON event data
https://api.pcowidget.com/v1/calendar-endpoint.php?key=YOUR_KEY&format=json&limit=5
# March 2026 month grid as HTML
https://api.pcowidget.com/v1/calendar-endpoint.php?key=YOUR_KEY&format=html&layout=table&month=2026-03
# Youth events as cards
https://api.pcowidget.com/v1/calendar-endpoint.php?key=YOUR_KEY&format=html&layout=cards&tag=Youth
# Date range query
https://api.pcowidget.com/v1/calendar-endpoint.php?key=YOUR_KEY&format=json&after=2026-03-01&before=2026-06-30&limit=50
JSON Schema
When using format=json, the response follows this structure:
{
"status": "ok",
"count": 12,
"events": [
{
"id": "123456", // EventInstance ID
"event_id": "789", // Parent Event ID
"name": "Sunday Worship", // EventInstance name (falls back to Event name)
"sermon_title": "Giving Expectantly", // Extracted from sermon: convention
"description": "Join us for worship...",
"starts_at": "2026-03-08T15:30:00Z", // UTC
"ends_at": "2026-03-08T16:30:00Z",
"all_day": false,
"location": "Sanctuary",
"image_url": "https://...",
"event_url": "https://...", // Church Center URL
"registration_url": "",
"featured": true,
"tags": ["Worship Services"], // Array of tag names
"recurrence": "weekly"
}
],
"meta": {
"filter": "",
"tag": null,
"layout": "cards",
"limit": 10,
"month": "2026-03",
"features": {
"popover": true,
"transitions": true,
"ical": true,
"tagColors": true,
"thisWeek": true
}
}
}
Troubleshooting
Widget shows nothing
- Open your browser's Developer Tools → Console tab and look for JavaScript errors or failed network requests
- Verify the script
srcURL loads directly in a browser tab — it should return JavaScript, not an error page - Test the endpoint directly:
https://api.pcowidget.com/v1/calendar-endpoint.php?key=YOUR_KEY&format=json&limit=1 - Confirm your API key is correct and your account is active
Squarespace: Make sure you're using a Code Block, not a Markdown block. Squarespace strips <script> tags from Markdown blocks.
CORS errors in browser console
If you see "Cross-Origin Request Blocked" or CORS errors:
- Your site's domain may not be on the allowed domains list for your account
- Get support through our contact form with your domain and API key to add it
- Both
https://example.comandhttps://www.example.comneed to be listed separately - Clear your browser cache after the domain is added
Events not showing / empty calendar
If you only just created or edited the event in Planning Center, see I changed something in Planning Center and the website hasn't caught up first. Otherwise:
- Test the JSON endpoint directly to verify your PCO credentials are working
- Confirm events exist and are published in Planning Center Calendar (not draft or hidden)
- If using
data-tag, verify the tag name matches exactly how it's spelled in Planning Center (matching is case-insensitive, but spelling must be exact) - Check that events are in the date range — by default the widget shows future events only
Event times look wrong
The widget shows every event in your church's own local time. It reads that timezone straight from your Planning Center organization settings, so there is no timezone attribute on the script tag and nothing for you to set on your website.
- Open Planning Center and check the timezone recorded for your organization. If it is wrong there, it will be wrong on your site
- Correct it in Planning Center. The widget re-checks the setting periodically and picks up the change on its own, with no edit to your embed code
- If Planning Center has no usable timezone for your organization, the widget falls back to Eastern time rather than showing nothing
- Times are stored in UTC by Planning Center and converted for display, so a single event never shows two different times on two pages of your site
Past events still visible
- Make sure
data-include-pastis not set to"true" - Hard refresh the page (Ctrl+Shift+R / Cmd+Shift+R) — the widget JavaScript may be cached
- If the issue persists, add a cache-busting query string to the script src:
calendar-widget.js?key=YOUR_KEY&v=2
I changed something in Planning Center and the website hasn't caught up
This is expected, and it sorts itself out. Give it about a minute, then reload the page once. Changes you make in Planning Center reach your website within roughly 60 seconds.
The delay works in both directions, which covers the two most common surprises:
- Something you added isn't there yet. A new event, a corrected time, a tag you just applied
- Something you removed is still there. An event you rejected, cancelled, deleted, or unpublished from Church Center
Why it happens: your widget doesn't call Planning Center on every single page view. It reuses a recent copy of your calendar for up to a minute, which is what keeps the widget loading quickly for your visitors instead of making every one of them wait on an API call. Once that minute is up, the next page load fetches your calendar fresh.
Refreshing over and over won't speed this up. The timing is on our server, not in your browser, so a hard refresh, a private window, or a different device will all show the same thing. Wait about a minute, then reload once.
If two widgets on your site are showing different things for a moment, that is the same delay. Each widget keeps its own copy, so they can catch up a few seconds apart. They will agree again shortly.
Still wrong after two or three minutes? Then this isn't the refresh
delay, and something else is going on. Check the event's publish and approval state
in Planning Center, confirm any data-tag spelling matches the tag exactly,
and make sure the event falls inside the date range your widget is showing. See
Events not showing / empty calendar above, or
get support through our contact form and we will take a look.
Sermon title not showing on simple tiles
- Confirm the line is in the Details field of the event in Planning Center Calendar (not the title or notes on a separate app)
- The line must begin with
sermon:(with a colon) — no space before the colon - The line can appear anywhere in the Details field, but must be on its own line
- Sermon titles only display on the
simplelayout
Need help? Get support through our contact form, and include your API key along with a description of the issue. Pro plan users receive priority response.