=== Gather ===
Contributors: ppricegather
Tags: obituary, funeral, memorial, livestream, gather
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.13.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Display Gather obituaries, search, carousel, and notification subscriptions on your funeral home WordPress site.

== Description ==

The Gather plugin connects your WordPress site to your Gather account and embeds live obituary data on any page through three shortcodes:

* `[gather-carousel]` — a scrolling carousel of recent obituaries, with hover preview and a "View All" link.
* `[gather-search]` — a full obituary directory with text search, year filter, A–Z filter, and pagination.
* `[gather-obit-subscribe]` — a popup that lets visitors sign up for an email notification whenever you publish a new obituary.

When a visitor follows an obituary link, the plugin serves a server-rendered obit page at `/obituaries/<slug>` on your domain. The page is rendered by PHP using live data from the Gather API, with real HTTP status codes (200 for found, 301 for canonical redirects, 404 for missing) so search engines treat the page correctly.

Customers who run the Gather Remember experience on their own domain can opt into a server-side proxy that forwards `/obituaries/<slug>` to the full Gather Remember React app. The proxy whitelists routes by token, caches responses, and surfaces upstream errors as an admin notice.

= What it doesn't do =

* The plugin does not send analytics, telemetry, or any data to Gather without a customer-initiated action. Settings only update when an admin saves them. The proxy only runs when the "Host Remember Pages" toggle is on.
* The plugin requires a normal dynamic WordPress install. It does not support static-site export workflows — obituary routing, canonical redirects, 404s, and the optional Remember-page proxy are all handled server-side by PHP at request time, which a static export can't reproduce.

= Multi-location funeral homes =

Each shortcode accepts an `fhkey` attribute to scope the obit list to a specific funeral home, and a `token` attribute to use a different website token. After activation, the full reference lives in WP at **Gather → Docs → Shortcode attributes**.

== Installation ==

1. From your WordPress admin dashboard, go to **Plugins → Add New**.
2. Search for "Gather" (or click **Upload Plugin** and select the `Gather-x.x.x.zip` you received from Gather).
3. Click **Install Now**, then **Activate Plugin**.
4. The new **Gather** top-level menu appears in the WordPress admin sidebar. Open **Gather → Status** for the first-run welcome card, or **Gather → Settings** to paste your integration key directly.
5. Paste your **Gather Integration Key** (contact Gather support if you do not have one) and select your environment (**Production** for live sites; **QA** for testing).
6. Click **Save Changes**, then **Gather → Status → Test Connection** to confirm the integration is live.
7. (Optional) **Gather → Pages → Create Obituaries page** drops a draft WordPress page containing the `[gather-search]` shortcode at your configured obituaries slug.

For shortcode attributes, multi-location setups, template customisation, and troubleshooting, see the in-WordPress documentation at **Gather → Docs**.

On WordPress Multisite, install + Network Activate the plugin from **Network Admin → Plugins**. Each site in the network can have its own Gather configuration.

== Frequently Asked Questions ==

= What happens to my settings when I deactivate or remove the plugin? =

Nothing — they stay in the database, so deactivating-then-reactivating preserves your configuration. If you want to remove all Gather data when uninstalling, enable **Delete all Gather data on uninstall** in the settings panel before uninstalling.

= Can I customize how each obituary card looks in the carousel or search results? =

Yes. The **Carousel JSRender Template** and **Search JSRender Template** fields in the settings panel accept HTML with [JSRender](https://www.jsviews.com/#jsrtags) tags. The available data fields are listed in the inline help next to each template editor.

= Can I customize the full obituary page (the one served at `/obituaries/<slug>`)? =

Yes. Your theme (or a child theme) can override the bundled template by hooking the `gather_obit_template` filter to return a different absolute file path. The bundled template at `src/Frontend/views/obit-page.php` is a reasonable starting point.

= Does the plugin work with caching plugins? =

Yes. All Gather output goes through standard WordPress rendering paths and respects normal page-cache lifecycles. The Remember-page proxy adds its own short-lived transient cache on top.

= Does the plugin work with my SEO plugin? =

Yes. The plugin only overrides the canonical link tag when you set the **Canonical URL** option, and only neutralizes RankMath's canonical/sitemap behavior when both RankMath and a canonical URL are configured. With no canonical URL set, your SEO plugin manages canonicals as usual.

= Does the plugin send data anywhere? =

The plugin makes outbound HTTP requests in these specific situations, and no others:

* When a visitor loads a page containing `[gather-carousel]` or `[gather-search]`, the visitor's browser requests obituary data from **your own site** (`/wp-json/gather/v1/obituaries`); your WordPress server then fetches it from the Gather API (`api.gather.app` for Production, `api.gatherqa.app` for QA) and caches it briefly. The visitor's browser never contacts the Gather API directly, and your integration key is never exposed in the page. (Obituary photos are still loaded by the browser from the Gather image CDN.) The most recent successful obituary list is also stored on your site so that, if the Gather API is ever briefly unavailable, the listing keeps showing your obituaries instead of going blank.
* When a visitor submits the `[gather-obit-subscribe]` form, their name and email are sent to your WordPress server (`/wp-json/gather/v1/subscribe`), which forwards the signup to the Gather API. The endpoint is rate-limited.
* When a visitor loads `/obituaries/<slug>` on your site, PHP fetches that case's data from the same Gather API endpoint to render the page server-side.
* When an admin clicks **Test Connection** on the Gather → Status page.
* When the **Host Remember Pages** toggle is on and a visitor loads `/obituaries/<slug>`, the plugin proxies the request to the Gather Remember service.
* When the **Expose an obituary sitemap** setting is on (the default), search-engine crawlers fetching `/obituary-sitemap.xml` or its child `/obituary-sitemap-<N>.xml` files trigger a proxied fetch to the Gather sitemap endpoint (cached for one hour). Your integration key stays on the server.

The plugin does not send analytics or usage telemetry, ever.

== External services ==

This plugin connects to **Gather** (https://gather.app), the obituary and memorial platform your funeral home uses. Gather is the source of the obituary data, search results, livestreams, notification sign-ups, sitemap, and — optionally — the full "Remember" memorial experience that the plugin displays on your WordPress site. The plugin is the bridge between your Gather account and your site, so it requires a Gather account and integration key to function.

It communicates with Gather's API and content-delivery network in the following cases, and no others:

* **Loading obituaries** (carousel/search widgets, an obituary page, or a sitemap fetch): your WordPress server requests obituary content from the Gather API (`api.gather.app` for Production, `api.gatherqa.app` for QA), authenticated with your integration key. No personal visitor data is sent — only the request for content.
* **Notification sign-up:** when a visitor submits the `[gather-obit-subscribe]` form, their name and email address are sent to the Gather API to register the subscription. This happens only on form submission.
* **Test Connection:** an admin-initiated request to the Gather API to verify the integration is working.
* **Host Remember Pages (off by default):** when an admin enables this option, visitor requests to `/obituaries/<slug>` are proxied to the Gather Remember service, and that page's static assets load from the Gather CDN (`my.gather.app` for Production, `my.gatherqa.app` for QA).
* **Obituary photos** shown in the widgets and pages are loaded by the visitor's browser from the Gather image CDN.

The plugin sends no analytics or usage telemetry.

Service provider: Gather Innovations.
Terms & Conditions: https://gather.app/terms-conditions/
Privacy Policy: https://gather.app/privacy-policy/

== Screenshots ==

1. Carousel of recent obituaries embedded in a funeral home homepage.
2. Search directory with year filter, A–Z filter, and pagination.
3. Server-rendered obit page at /obituaries/&lt;slug&gt;.
4. Subscription popup for obituary email notifications.
5. The Gather admin status page, showing integration health and detected integrations.

== Changelog ==

= 2.0.0 (planned) =

* Removed the optional WP2Static static-site integration entirely. The plugin now requires a normal dynamic WordPress install; obituary routing, redirects, and 404s are handled server-side and can't be statically exported.
* RankMath canonical/sitemap overrides are gated behind both the canonical setting and RankMath being present. Sites with no SEO plugin or a different SEO plugin are no longer affected.
* PSR-4 autoloader (`Gather\\` → `src/`). All classes namespaced.
* New top-level `Gather` admin menu with Status / Settings / Templates / Pages / Apple Pay / Advanced subpages (Phase 3).
* Server-rendered obit page replaces the static-era "obit-lite" client-rendered template. Real HTTP redirect + 404 status codes. The `gather_obit_url` and `gather_obit_name` regex settings are no longer needed.
* Host-remember-page proxy modernized: URL whitelist, `wp_remote_request` (no raw curl), header allowlist, transient cache, dismissible admin notice on upstream 5xx.
* Frontend asset hygiene: no more global Google Fonts enqueue, no more Slick carousel library. Per-shortcode CSS so pages without Gather shortcodes load zero Gather assets.
* Escape & sanitize audit across canonical link, settings renderers, shortcode inline JS config, Apple Pay endpoint.
* Optional `gather_cleanup_on_uninstall` — delete all Gather settings and cached data on uninstall.
* Server-side proxy for the carousel/search widgets: the browser talks only to your own site; the integration key stays on the server. Last-known-good obituaries are served if the Gather API is briefly unavailable, so listings never go blank.
* Obituary sitemap published at `/obituary-sitemap.xml` (on by default), advertised in robots.txt and your SEO plugin's sitemap index.
* Server-rendered obituary pages now link into the full memorial page — "Continue reading the full obituary", "View full service details", and "Share a memory" — and display birth/death dates correctly regardless of site timezone.
* New obituary redirect manager (Gather → Redirects): import a CSV (paste or upload) mapping legacy obituary URLs to their new Gather pages as 301 redirects, optionally archiving the old published page/post to Draft so it leaves the sitemap. A searchable, paginated table lists every redirect with per-row edit (target) and delete; deleting or clearing restores any pages that were archived.

= 1.13.1 =

* Host Remember: the reverse-proxy response cache is now keyed on the request path only (the query string is ignored), and missing `/static` assets are no longer negatively cached. This prevents arbitrary query strings or paths from creating unbounded cache entries.

= 1.13.0 =

* Renamed the `apple_pay_merchant_id` option to `gather_apple_pay_merchant_id` so every plugin option carries the `gather_` prefix. Existing values migrate automatically on upgrade.
* Settings import (Gather → Advanced) now runs imported values through the same sanitization callbacks as a normal settings save.
* The host-remember proxy's asset-rewrite shim tag is now built with core's `wp_get_script_tag()`.
* Host Remember: the `/obituaries/_redirect` auth-handoff page (used by the "Organize" link to carry a signed-in session back into the Gather app) is now proxied instead of falling through to a 404.
* Obituary pages are now always served under `/obituaries/`. The configurable "Obituaries page path" setting has been removed (the Gather service standardizes on this path); any previously saved value is cleaned up automatically on upgrade.

= 1.11.0 =

* Remove snap scrolling on carousel; switch to natural overflow scrolling.

= 1.10.0 - 1.10.2 =

* Date format option on all shortcodes (`date_format` attribute).
* Multi-location funeral home support via `fhkey` / `token` shortcode attributes.

= 1.0.0 - 1.9.0 =

* Initial plugin development.
* Obituary carousel, search, and subscription popup shortcodes.
* Optional WP2Static integration for static-site export workflows.

== Upgrade Notice ==

= 2.0.0 =

Major release. Obituary pages are now served by a real PHP route (no static template or client-side fetch), the WP2Static integration is removed (dynamic-only), and the gather_obit_url/gather_obit_name settings are gone. Your settings carry over.
