Title: Open Growth Preferred Source Button for Google
Author: jaimepaezv
Published: <strong>October 13, 2026</strong>
Last modified: October 13, 2026

---

Search plugins

![](https://s.w.org/plugins/geopattern-icon/open-growth-preferred-source-button-
for-google.svg)

# Open Growth Preferred Source Button for Google

 By [jaimepaezv](https://profiles.wordpress.org/jaimepaezv/)

[Download](https://downloads.wordpress.org/plugin/open-growth-preferred-source-button-for-google.1.1.5.zip)

 * [Details](https://wordpress.org/plugins/open-growth-preferred-source-button-for-google/#description)
 * [Reviews](https://wordpress.org/plugins/open-growth-preferred-source-button-for-google/#reviews)
 *  [Installation](https://wordpress.org/plugins/open-growth-preferred-source-button-for-google/#installation)
 * [Development](https://wordpress.org/plugins/open-growth-preferred-source-button-for-google/#developers)

 [Support](https://wordpress.org/support/plugin/open-growth-preferred-source-button-for-google/)

## Description

Open Growth Preferred Source Button for Google integrates Google’s documented Preferred
Sources JavaScript button into WordPress.

Independent plugin, not affiliated with or endorsed by Google.

Features:
 * Uses Google’s documented `publisher.js` integration and declarative
button attributes. * Optional custom-control mode using Google’s documented manual/
programmatic integration. * Custom controls can use a unique CSS selector or the`
data-ogpsb-preferred-source` attribute, including native Bootstrap 5.3 / LiveCanvas
markup. * Automatic placement before, after, or both before and after singular content.*
Selectable public, publicly queryable post types. * Per-content visibility control
in the block editor sidebar. * Light/dark theme, supported language override, translated
language names in the admin UI, and direction-aware alignment. * Shortcode: `[open_growth_preferred_source]`.*
Dynamic Gutenberg block: `open-growth/preferred-source-button`. * Early asset enqueue
on pages where a button is expected, with configurable reserved height to reduce
layout shift. Set the reserved height to `0` to disable it. The async Google script
and layout CSS are loaded early when a placement is predictable; late manual placements
receive a footer fallback so they still work and remain styled. * Protected posts,
feeds, embeds, AMP requests, and explicitly hidden content do not render the button.*
No remote calls from PHP. * Read-only on-demand diagnostics in Settings to explain
whether a specific post is configured for automatic or manual display, without contacting
Google or changing settings.

Google only supports domain-level and subdomain-level publications in its Preferred
Sources tool. Eligibility is controlled by Google, not by this plugin.

### Shortcode

    ```
    [open_growth_preferred_source]
    ```

Example:

    ```
    [open_growth_preferred_source theme="dark" lang="es" alignment="center"]
    ```

Allowed values:
 * `theme`: `light`, `dark` (case-insensitive). * `lang`: a supported
Google language code. An explicit `lang=""` forces automatic browser language. *`
alignment`: `start`, `center`, `end`. `left` and `right` are accepted as aliases.

Invalid values fall back to the corresponding plugin setting.

### External services

This plugin loads Google’s Preferred Sources JavaScript library from `https://news.
google.com/swg/js/v1/publisher.js`. In standard mode it is loaded on front-end pages
where a button is expected to appear. In Custom control mode it is loaded on normal
front-end pages because the trigger may live in a theme template, header, builder
partial, popup, or dynamically inserted markup that WordPress cannot reliably predict
server-side. The browser therefore makes a request to Google when that script loads.
Google may receive standard request information such as the visitor’s IP address,
browser/user-agent data, referrer information, and other data handled by Google’s
service.

The library is required to render and operate Google’s interactive Preferred Source
button. No request to Google is made by this plugin’s PHP code.

Service documentation: https://developers.google.com/search/docs/appearance/preferred-
sources
 Google Terms: https://policies.google.com/terms Google Privacy Policy: 
https://policies.google.com/privacy

## Blocks

This plugin provides 1 block.

 *   Preferred Source Button for Google Displays the Preferred Source button for
   Google.

## Installation

 1. Upload the plugin ZIP in Plugins > Add New > Upload Plugin.
 2. Activate it.
 3. Go to Settings > Preferred Source Button.
 4. Configure placement, content types, theme, language, and alignment.

For a custom site control, choose **Custom control**. Add `data-ogpsb-preferred-
source` to an existing HTML element or configure a unique CSS selector. In custom-
control mode the plugin does not render Google’s standard button.

This release uses its own option and metadata names and does not migrate settings
from earlier differently named builds.

## FAQ

### Is this plugin affiliated with Google?

No. Independent plugin, not affiliated with or endorsed by Google.

### Does installing the plugin make my site eligible for Preferred Sources?

No. Check that your site appears in Google’s Preferred Sources tool; this plugin
cannot make a site eligible.

Preferred Sources tool: https://www.google.com/preferences/source

Google documentation: https://developers.google.com/search/docs/appearance/preferred-
sources

### Are WordPress sites installed in subdirectories supported by Google?

Google documents eligibility at the domain and subdomain level only. A URL such 
as `example.com/blog/` is not independently eligible. The settings screen shows 
a warning when `home_url()` contains a subdirectory path.

### Why is the live Google button not shown inside the block editor?

The editor intentionally displays a stable placeholder. Google’s external library
is not loaded into the editor merely to provide a preview. The live button renders
on the front end.

### How does automatic placement work with page builders?

The plugin uses WordPress `the_content` by default and includes dedicated frontend-
output integration for Elementor (`elementor/frontend/the_content`) and Bricks (`
bricks/frontend/render_data`, content area only). This covers builder layouts that
bypass the normal WordPress content pass while preserving the same eligibility, 
duplicate, password, and per-content visibility checks.

Oxygen does not apply WordPress `the_content` to Oxygen-designed singular content
by default. Oxygen provides its own setting to enable that filter. If you keep that
setting disabled, place the plugin shortcode where you want the button. For LiveCanvas
and other builders, automatic placement works when the builder ultimately runs `
the_content`; otherwise use the shortcode in the builder output. The plugin does
not modify another builder’s settings.

Dynamic content inserted after Google’s library has initialized is still subject
to Google’s standard declarative-mode limitation described below.

### Can I disable the reserved minimum height?

Yes. Set **Reserved minimum height** to `0` in Settings > Preferred Source Button.
The `ogpsb_button_min_height` filter can still override the stored value.

### What happens when uninstalling on a very large multisite network?

Uninstall removes the plugin option and `_ogpsb_hide` post meta from every site 
in batches of 100. This avoids loading the complete site list into memory, but WordPress
uninstall runs synchronously. On exceptionally large networks, host execution-time
limits can interrupt cleanup before every site has been processed. If that applies
to your network, run uninstall from a maintenance window or remove the two plugin
data keys with a network-aware administrative process.

### What about content injected after the page has loaded?

Google’s standard implementation scans the DOM when its library initializes, so 
declarative buttons inserted later may not be rendered automatically. The plugin’s
Custom control mode uses Google’s documented manual/programmatic API plus delegated
click handling, so matching custom triggers added later can work without a DOM re-
scan.

### How do custom controls work with LiveCanvas, Picostrap, or Bootstrap 5.3?

Use ordinary HTML and keep your existing Bootstrap classes. For example: `<button
type="button" class="btn btn-primary" data-ogpsb-preferred-source>Add to preferred
sources</button>`. The plugin uses native JavaScript and its own `data-ogpsb-preferred-
source` attribute; it does not depend on jQuery or Bootstrap JavaScript and does
not use Bootstrap’s `data-bs-*` namespace.

### Why does Custom control mode load its scripts on every normal frontend page?

Custom triggers can live outside post content—in a header, footer, template, popup,
builder partial, or markup inserted later by JavaScript—so the plugin cannot reliably
predict server-side which URLs contain a trigger. Custom control mode therefore 
loads Google’s library and the small trigger controller on normal frontend pages
by design. If site-wide loading is not appropriate for your site, use the standard
implementation or conditionally dequeue the integration in site-specific code.

### Does the per-content visibility setting affect Custom Fields support?

No. The editor uses a dedicated REST field backed by the plugin’s private metadata
key, so the plugin does not enable WordPress Custom Fields support or expose the
Custom Fields UI merely to persist this setting.

### What happens on AMP pages?

The plugin suppresses the button and third-party script on requests detected through
the official AMP plugin’s `amp_is_request()` function.

### What if my site uses Content-Security-Policy (CSP)?

Google’s documented implementation loads `https://news.google.com/swg/js/v1/publisher.
js`. Sites with a restrictive CSP must allow the required Google origin in their`
script-src` policy. Google’s documented standard snippet does not include a Subresource
Integrity (`integrity`) attribute, so this plugin does not invent one for a remotely
mutable script.

### Which filters are available?

 * `ogpsb_should_display` — `(bool $should_display, WP_Post $post)`.
 * `ogpsb_button_html` — `(string $html, array $args)`.
 * `ogpsb_script_attributes` — associative array of extra script attributes.
 * `ogpsb_button_min_height` — reserved wrapper height in pixels; its input value
   is the saved setting (`40` by default, `0` disables reservation).
 * `ogpsb_languages` — supported language code/name map. Use only codes accepted
   by Google.
 * `ogpsb_enable_elementor_integration` — boolean; return `false` to bypass the 
   dedicated Elementor automatic-placement integration.
 * `ogpsb_enable_bricks_integration` — boolean; return `false` to bypass the dedicated
   Bricks automatic-placement integration.

### Does placement “Before and after” render two buttons?

Yes. That setting deliberately renders one button before and one after the content.
Use a single-placement option if you want only one instance.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Open Growth Preferred Source Button for Google” is open source software. The following
people have contributed to this plugin.

Contributors

 *   [ jaimepaezv ](https://profiles.wordpress.org/jaimepaezv/)

[Translate “Open Growth Preferred Source Button for Google” into your language.](https://translate.wordpress.org/projects/wp-plugins/open-growth-preferred-source-button-for-google)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/open-growth-preferred-source-button-for-google/),
check out the [SVN repository](https://plugins.svn.wordpress.org/open-growth-preferred-source-button-for-google/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/open-growth-preferred-source-button-for-google/)
by [RSS](https://plugins.trac.wordpress.org/log/open-growth-preferred-source-button-for-google/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.1.5

 * Load admin settings JavaScript through WordPress enqueue APIs instead of an inline
   script tag.
 * Sanitize final filterable button markup with an explicit HTML allowlist.
 * Remove bundled translations intended for WordPress.org translation infrastructure.

#### 1.1.4

 * Fixed Custom control clicks that occur before Google’s async client is ready:
   configured triggers now suppress their native action immediately and queue one
   invocation until initialization completes.
 * Added an explicit late-style fallback for manual buttons first discovered after`
   wp_head`, so alignment and reserved-height CSS are not silently omitted.
 * Added early archive/posts-page scanning for stored shortcode, dynamic block, 
   or declarative Google button markup, preserving early CSS/script loading when
   those manual placements are predictable.
 * Restored per-content visibility for shortcode/block placements rendered inside
   non-singular loops, without treating archive term/user IDs as post IDs.
 * Aligned early asset prediction with Diagnostics by recognizing stored `google-
   add-preferred-source-btn` markup as a supported manual placement.
 * Revalidated the minimum supported WordPress version as 6.5. `wp_is_rest_endpoint()`
   was introduced in WordPress 6.5; the 7.0 minimum stated in the 1.0.4/1.0.5 historical
   notes was unnecessarily restrictive.
 * Made the unexplained 1.1.2 changelog gap explicit without retroactively inventing
   release changes.
 * Bumped plugin, block metadata, and stable-tag versions consistently to 1.1.4.
 * Documented the intentional site-wide frontend asset loading used by Custom control
   mode for global and dynamically inserted triggers.
 * Added filters to disable the dedicated Elementor or Bricks automatic-placement
   integrations without adding persistent settings.
 * Reordered the historical changelog so versions remain in descending order.
 * Added browser-native CSS selector syntax validation on the settings screen so
   invalid Custom control selectors cannot be saved unnoticed.

#### 1.1.3

 * Corrected diagnostics for password-protected content so unlocked content is not
   reported as permanently suppressed, and made explicit that `ogpsb_should_display`
   is not executed from the admin diagnostic because callbacks may depend on frontend
   context.
 * Hardened custom-selector storage and inline JavaScript encoding while preserving
   legitimate percent-encoded CSS selector sequences.
 * Replaced REST-backed `meta` editing with a dedicated boolean REST field, so unchecking
   deletes `_ogpsb_hide`, the sidebar updates only its own field, and the plugin
   no longer enables the Custom Fields UI.
 * Prevented automatic/manual duplicates regardless of whether a shortcode/block
   or automatic placement renders first.
 * Removed the redundant shortcode `lang=""` branch without changing automatic-language
   behavior.
 * Allowed explicit shortcode and dynamic-block rendering on non-singular front-
   end views such as archives and the posts page; automatic placement remains singular-
   only.
 * Cleaned packaged PO/POT translator headers.

#### 1.1.2

 * Historical note: the 1.1.3 source package contained no 1.1.2 changelog entry.
   No changes are retroactively attributed to this version.

#### 1.1.1

 * Fixed Elementor automatic placement to use the document currently rendered by
   Elementor, preventing Theme Builder headers, footers, or popups from consuming
   the singular-content insertion.
 * Fixed Custom control settings UI so the Content types row is hidden with the 
   other standard-only placement controls.
 * Registered the bundled `/languages` directory on `init` so packaged translations
   load reliably in non-WordPress.org installations.
 * Hardened the language maintenance tool against web execution and allowed `--check`
   to validate legacy generated lists that predate a recorded source hash.
 * Restored release packaging hygiene by excluding repository-only `.distignore`
   and `phpcs.xml.dist`.

#### 1.1.0

 * Added Google’s documented manual/programmatic Preferred Sources integration as
   an opt-in Custom control mode.
 * Added an optional custom CSS trigger selector and the builder-friendly `data-
   ogpsb-preferred-source` trigger attribute.
 * Added a small native-JavaScript delegated controller so triggers in LiveCanvas,
   templates, headers, popups, and dynamically inserted markup can invoke the flow
   without jQuery or Bootstrap coupling.
 * Added the required `preferred-sources-control="manual"` attribute only in Custom
   control mode; the existing standard mode remains unchanged.
 * Updated Gutenberg editor messaging and settings UI so standard-only controls 
   are not presented as applicable in Custom control mode.
 * Added custom-mode diagnostics without executing builders or contacting Google.

#### 1.0.9

 * Added a read-only diagnostics section in Settings for checking one post/page/
   CPT by ID.
 * Diagnostics report public visibility, password protection, per-content hiding,
   automatic-display configuration, selected content type, stored manual placement,
   expected Google script loading, and custom visibility-filter presence.
 * The diagnostic runs only on demand, makes no request to Google, changes no settings,
   and clearly distinguishes configuration checks from actual theme/page-builder
   execution.

#### 1.0.8

 * Optimized duplicate-button detection with a cheap string pre-check before invoking`
   WP_HTML_Tag_Processor`.
 * Added per-request caching for candidate HTML that contains the marker string,
   avoiding repeated structural scans when builders or filters process the same 
   rendered content more than once.
 * Structural validation is still performed before treating the marker as a real
   button, so plain-text mentions do not suppress automatic placement.

#### 1.0.7

 * Added a deterministic release tool for refreshing and verifying the supported-
   language whitelist from Google’s official CSV.
 * The release tool validates the CSV schema and language tags, rejects duplicates
   and malformed/empty responses, records the source SHA-256, writes atomically,
   and supports a non-mutating `--check` mode for CI/release gates.
 * The official CSV remains a build/release dependency only; WordPress runtime performs
   no language-list network requests.

#### 1.0.6

 * Added dedicated automatic-placement integration for Elementor frontend output
   and Bricks content-area rendering while retaining the standard `the_content` 
   path.
 * Documented Oxygen and LiveCanvas/page-builder behavior and the recommended shortcode
   fallback when a builder bypasses `the_content`.
 * Added a configurable reserved minimum-height setting from 0 to 500 px; `0` disables
   layout reservation.
 * Localized the language display names through the plugin text domain while keeping
   canonical Google language codes unchanged.
 * Added repository-quality `phpcs.xml.dist` and `.distignore` files to the distribution
   package as requested.
 * Documented synchronous uninstall limitations for exceptionally large multisite
   networks; cleanup remains batched at 100 sites per query.

#### 1.0.5

 * Resolved manual-render post context from the singular queried object so stale
   global post data from secondary loops cannot affect visibility decisions.
 * Registered the Classic Editor fallback per actual post editor using `use_block_editor_for_post()`,
   including sites where the Classic Editor plugin disables the block editor for
   an otherwise block-capable post type.
 * Replaced plain-text duplicate detection with HTML-aware detection of the actual`
   google-add-preferred-source-btn` attribute, preventing tutorial text from suppressing
   automatic placement.
 * Added the block metadata `version` field for explicit block asset/version metadata.
 * Documented that REST-backed per-content visibility may require enabling WordPress
   Custom Fields support on selected post types.
 * At the time, kept WordPress 7.0 as the minimum supported core version and removed
   an unnecessary compatibility guard around `WP_HTML_Tag_Processor`; the minimum-
   version rationale was later corrected to WordPress 6.5 in 1.1.4.

#### 1.0.4

 * Raised the minimum supported WordPress version to 7.0 and removed compatibility
   branches for older core versions. This minimum was later corrected to WordPress
   6.5 in 1.1.4 after revalidating the core API requirements.
 * Split the block editor UI from the post visibility sidebar so `wp-editor` is 
   loaded only on supported post-editing screens, not in the Site Editor or Widgets
   editor.
 * Declared the block editor script in `block.json` and kept the block on API version
   3.
 * Switched REST-context detection to WordPress core `wp_is_rest_endpoint()`. The
   function was subsequently revalidated as available since WordPress 6.5, which
   is why the minimum was corrected in 1.1.4.
 * Removed the server-side WP Consent API check because page caching can make per-
   visitor consent decisions unsafe at render time; consent integration remains 
   intentionally outside this plugin’s scope.
 * Replaced per-request plugin-header parsing with the `OGPSB_VERSION` constant.
 * Removed the non-URI `Update URI: false` header; WordPress.org-hosted plugins 
   should not declare a third-party update URI.
 * Added a separate JavaScript translation catalog for the post visibility sidebar.
 * Enqueued the tiny layout-reservation style early on eligible singular requests,
   including manual placements that may come from template parts or builders.
 * Cached per-post visibility decisions within a request and improved the block 
   editor inherited-language label.
 * Release ZIP excludes repository-only `.distignore` and `phpcs.xml.dist` files.
 * Kept `Contributors: jaimepaezv`.

#### 1.0.3

 * Changed WordPress.org contributor placeholder to `jaimepaezv`.
 * Fixed late-registered custom post type settings and delayed visibility-meta registration
   until init priority 99.
 * Updated the editor sidebar to the current `wp.editor` SlotFill and reactive `
   useSelect`/`useDispatch` data hooks.
 * Ensured selected post types support REST-backed custom fields so the visibility
   toggle persists.
 * Added Classic Editor/page-builder fallback visibility control without forcing
   a classic meta box into the block editor.
 * Suppressed manual rendering in REST, archive, preview, and Customizer contexts.
 * Added packaged JavaScript translations for the editor and included block metadata
   strings in translation catalogs.
 * Added an `ogpsb_languages` filter while retaining the embedded-list verification
   warning until the official CSV can be compared.
 * Replaced the abbreviated license file with the complete GPL v2 text.

#### 1.0.2

 * Removed compatibility coupling to earlier builds by using a unique namespace,
   constants, option name, metadata key, shortcode, block name, handles, and filters.
 * Fixed block setting inheritance by removing attribute defaults from `block.json`;
   unset attributes now inherit plugin settings and the block can explicitly choose
   automatic browser language.
 * Upgraded the block to API version 3, added `useBlockProps()`, a selectable editor
   wrapper, a stable visual placeholder, translated controls, and select-based language
   input.
 * Replaced the classic visibility meta box with registered REST post meta and a
   block-editor document settings panel.
 * Enqueued front-end assets early from singular query context rather than relying
   on loop state, so reserved height CSS can be present before content rendering.
   Predicted buttons load Google’s async script in the head; late manual rendering
   has a footer-only fallback.
 * Prevented excerpt generation from consuming the automatic-injection guard and
   moved automatic injection after block/shortcode processing for stronger duplicate
   detection.
 * Added context-safe post resolution so archive term/user IDs are never treated
   as post IDs.
 * Switched alignment to logical start/center/end values for RTL compatibility while
   accepting left/right shortcode aliases.
 * Added AMP suppression when the official AMP detection function is available.
 * Limited selectable post types to public and publicly queryable types.
 * Replaced regex script-tag mutation with `WP_HTML_Tag_Processor`.
 * Cached the embedded language list per request and removed duplicate Chinese locale
   aliases from the embedded canonical list.
 * Moved all translatable source strings to English and added editor-script translation
   loading.
 * Added the required External services disclosure with service, terms, and privacy
   links.
 * Added optional WP Consent API interoperability without adding a hard dependency.
 * Updated WordPress.org metadata to `Tested up to: 7.1`.
 * Added `phpcs.xml.dist` and `.distignore` for release-quality tooling.

#### 1.0.1

 * Previous internal build.

## Meta

 *  Version **1.1.5**
 *  Last updated **2 days ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.5 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [google search](https://wordpress.org/plugins/tags/google-search/)[news](https://wordpress.org/plugins/tags/news/)
   [preferred source](https://wordpress.org/plugins/tags/preferred-source/)[publisher](https://wordpress.org/plugins/tags/publisher/)
   [search](https://wordpress.org/plugins/tags/search/)
 *  [Advanced View](https://wordpress.org/plugins/open-growth-preferred-source-button-for-google/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/open-growth-preferred-source-button-for-google/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/open-growth-preferred-source-button-for-google/reviews/)

## Contributors

 *   [ jaimepaezv ](https://profiles.wordpress.org/jaimepaezv/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/open-growth-preferred-source-button-for-google/)