BDC Print PDF (ACF Page Builder)
A WordPress plugin that adds a [bdc_print_pdf] shortcode rendering a "Download PDF" button. Clicking it streams a simplified, one-column PDF of the current post, built from ACF Insight fields and a filtered subset of the page_builder flexible content.
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/bonsai-systems/bdc-print-pdf/archive/refs/heads/main.zipBonsai Print PDF (ACF Page Builder)
A WordPress plugin that adds a [bdc_print_pdf] shortcode rendering a "Download PDF" button. Clicking it streams a simplified, one-column PDF of the current post, built from ACF Insight fields and a filtered subset of the page_builder flexible content.
Features
[bdc_print_pdf label="Download PDF" class="bdc-print-pdf-button"]shortcode — only renders on singular posts of an eligible post type (see "Eligible post types" below).- PDF generation via the bundled Dompdf library (no Composer dependency at runtime — the
dompdf/folder is vendored directly). - Content pulled from:
- Top-level ACF fields:
insight_headline,insight_introduction,associated_authors(relationship field) — rendered as a header with title, intro, author photos and byline. legacy_contentACF field, if present.- The
page_builderACF Flexible Content field — onlyinsights_content_modulerows are included, and only rows withcontent_typeofcontent-text,content-quote,content-table, orcontent-type-table. Video, image, and two-image blocks are intentionally skipped to keep the PDF compact. - Ninja Tables shortcodes (
[ninja_tables id="..."]) found in text or table blocks are expanded to static HTML tables — read directly from thewp_ninja_table_itemsDB table where possible, falling back todo_shortcode()output.
- Top-level ACF fields:
- Footer added to every PDF page via the Dompdf canvas: a clickable "Read the full insight" link (bottom-left) and
page_num / page_count(bottom-right). - First-page logo pulled from the ACF Options field
site_main_logo. - Looks for a dedicated print stylesheet at
assets/css/core/print-pdf.cssin the active child theme first, then the parent theme, and loads it via<link>if found. - Request handling is via a custom query var (
bdc_print_pdf=1) ontemplate_redirect. The URL is stable per post (no nonce, no expiry) — see "PDF endpoint behaviour" below.
Eligible post types
The PDF endpoint only serves singular posts of an allowed post type, filterable via bdc_print_pdf_post_types (default: array( 'post' )):
add_filter( 'bdc_print_pdf_post_types', function ( $types ) {
return array( 'post', 'insights' );
} );
Requests against any other post type (or content that doesn't resolve to a valid post) return 404. This plugin ships to multiple Bonsai sites via the same GitHub release, so this is a filter rather than a hard-coded post type — confirm the correct value for each site before relying on the default.
PDF endpoint behaviour
As of 3.1.0, the endpoint no longer uses a nonce. It previously did (bdc_print_pdf_{$post_id}, verified in template_redirect), but since the endpoint only ever renders a published, publicly-viewable post, there was no state-changing action for the nonce to protect, and it rotated the URL every 12–24 hours. That made the URL uncacheable and, once an expired-nonce URL got indexed, caused it to 500 indefinitely (a bare wp_die() defaults to HTTP 500) — Google recrawls a 500 forever on the assumption it's transient, which on the Dixcart site alone produced ~6,200 indexed, permanently-broken PDF URLs.
Current behaviour:
| Request | Response |
|---|---|
?bdc_print_pdf=1 on an eligible post |
200, application/pdf, Cache-Control: public, max-age=… (filterable via bdc_print_pdf_cache_seconds, default 1 hour), X-Robots-Tag: noindex, nofollow |
?bdc_print_pdf=1&bdc_pp_nonce=<anything> |
410 Gone — legacy nonce URLs are permanently retired, regardless of whether the nonce value would still verify |
?bdc_print_pdf=1 on a non-eligible post type, or an invalid post |
404 |
| Dompdf library missing | 404, with the underlying cause logged via error_log() |
No code path returns a 5xx. Every response — success or failure — carries X-Robots-Tag: noindex, nofollow, since the PDF duplicates the article it's generated from and shouldn't compete with it in search.
Requirements
- WordPress 6.0+
- PHP 8.0+
- ACF (Advanced Custom Fields / ACF Pro) — the plugin degrades gracefully to raw post content if ACF is not active, but the Insight-specific header/fields require it.
- The
dompdf/folder must be present inside the plugin directory (already vendored in this repo).
Usage
- Activate the plugin.
- Add
[bdc_print_pdf]to a template or the page builder where you want the download button to appear. - Optional shortcode attributes:
label— button text (default:Download PDF)class— CSS class on the<a>tag (default:bdc-print-pdf-button)
Data / Fields Used
No custom options are stored by this plugin — it only reads existing ACF field data at request time:
| Field | Type | Used for |
|---|---|---|
insight_headline |
Text | PDF header title (falls back to post title) |
insight_introduction |
Textarea | PDF header intro |
associated_authors |
Relationship | Author photos + byline links |
legacy_content |
WYSIWYG | Optional legacy content block |
page_builder |
Flexible Content | Filtered insights_content_module rows |
site_main_logo |
Image (Options page) | First-page logo |
Security Note
Field values (insight_headline, insight_introduction, legacy_content, module text/quote/table content) are output largely as-authored (via wp_kses_post() or, for the headline/intro, directly) so that editor-authored HTML formatting survives into the PDF. Access to author these fields is restricted to users who can edit the relevant post type — there is no public-facing input on this plugin. The PDF endpoint itself is read-only (it renders an already-public post) and unauthenticated by design; see "PDF endpoint behaviour" above for why it has no nonce.
Updates
Ships with YahnisElsts/plugin-update-checker (installed via Composer, vendor/ committed) pointed at github.com/Bonsai-Systems/bdc-print-pdf. Sites with the plugin installed will see updates in Plugins in wp-admin, same as bonsai-code-injector and bonsai-maintenance.
To ship a new version:
- Bump the
Version:header and theBDC_PP_VERSIONconstant inbdc-print-pdf.php, and add aCHANGELOG.mdentry. - Commit and push to
main. - Publish a GitHub Release tagged with the new version (release-assets mode is enabled, so attach a zip of the plugin folder — plain source-archive tags won't be picked up).
Sites check for updates every 6 hours ($checkPeriod argument to buildUpdateChecker()), or immediately if an admin clicks "Check again" on the Plugins screen.
Releases
1 release.
These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.