=== fraew Custom Adverts ===
Contributors: fraew
Donate link: https://buymeacoffee.com/fraew
Tags: advertising, ads, widget, analytics, banner
Requires at least: 5.0
Tested up to: 7.0
Requires PHP: 7.2
Stable tag: 1.4.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Sell your own ad space to real advertising customers. Add image adverts with a link, place them in widgets, and track views, clicks and CTR.

== Description ==

fraew Custom Adverts is a lightweight way to sell your own ad space directly to advertising customers, rather than relying on a third-party ad network.

Create an advert for each advertiser (an image plus a target link), place it in any widget area, and the plugin automatically records views, clicks and click-through rate (CTR) so you can show advertisers exactly what their placement delivered.

**Features**

* Create adverts with a title, target URL and image
* Display any advert in any widget area via the Custom Advert widget
* Rotating adverts — select multiple adverts per widget and display a random one on each page load
* Per-advert analytics: views, clicks and CTR
* Filter analytics by the last 7, 30, 90 or 365 days
* Pricing templates — create flexible pricing rules (CPM, CPC, daily/monthly flat rates)
* Monthly email reports — send advertisers automatic performance summaries with costings (optional)
* Costings dashboard — assign pricing templates to adverts and track costings automatically
* Simple admin screen with step-by-step guidance — no shortcodes or code editing required

**Why sell ad space directly?**

* Keep all of the revenue — no network taking a cut
* Choose your own advertisers and creative
* Sell to real, local businesses who value guaranteed placement on a site their customers already read
* Use the built-in analytics to justify pricing and renewals with real numbers

= Support =

If this plugin helps you sell ad space, consider [buying me a coffee](https://buymeacoffee.com/fraew).

== Installation ==

1. Upload the plugin files to `/wp-content/plugins/fraew-custom-adverts`, or install the plugin through the WordPress plugins screen directly.
2. Activate the plugin through the 'Plugins' screen in WordPress.
3. The plugin automatically creates its database tables on activation — no further setup is required.

= Creating an advert =

1. Go to **Custom Adverts → Add New**.
2. Enter a Title (for your own reference), the advertiser's target URL, and upload their image.
3. Click **Publish**.

= Displaying an advert =

1. Go to **Appearance → Widgets**.
2. Add a **Custom Advert** widget to any widget area.
3. Select which advert it should display and save.

= Reviewing performance =

1. Go to **Custom Adverts → Analytics**.
2. Select a reporting period.
3. Review views, clicks and CTR for each advert.

== Frequently Asked Questions ==

= Can I display the same advert in more than one place? =

Yes. Add the same advert to multiple widget areas — its analytics are combined across every placement.

= Can I run more than one advert at a time? =

Yes, there's no limit to the number of adverts you can create or display.

= How is a "view" counted? =

A view is recorded when a widget containing an advert loads on a page, tracked via a nonce-verified AJAX request.

= How is a "click" counted? =

A click is recorded when a visitor clicks the advert image. The link opens in a new tab.

= Does this plugin phone home or use any external services? =

No. All tracking data is stored in your own WordPress database; the plugin does not send data anywhere else.

= The Custom Advert widget won't save in the block-based Widgets screen =

If adding the widget fails with a browser "connection closed" error, this is almost always a security firewall (WAF / mod_security) on your host blocking the block widget editor's REST requests. It is not specific to this plugin — any classic widget fails the same way on such hosts. Two fixes: ask your host to allow the `/wp-json/` requests for logged-in administrators, or switch to the classic Widgets screen (the official "Classic Widgets" plugin, or a small must-use plugin that calls `add_filter( 'use_widgets_block_editor', '__return_false' )`).

== Privacy ==

fraew Custom Adverts does not transmit data to external servers. All analytics data is stored in your WordPress database.

When tracking advert views and clicks, the plugin records:
- **Visitor IP address** — used for session-based deduplication (prevents counting the same view multiple times per page load)
- **User agent string** — browser and device information, used for analytics reporting

This data is retained in your database per your WordPress backup and retention policies. It is never shared with third parties. You are responsible for notifying site visitors about analytics tracking if legally required (e.g. GDPR, CCPA). Consider adding a privacy policy statement if you operate in a jurisdiction that requires it.

== Screenshots ==

1. Costings Templates admin screen — manage your pricing rules (CPM, CPC, daily/monthly flat rates).
2. Create or edit a pricing template with flexible pricing options and view affected adverts.
3. The Custom Adverts list showing each advert's assigned pricing template at a glance.
4. Monthly costings report email sent to advertisers with performance metrics and pricing breakdown.
5. Admin notification showing which adverts were updated when a pricing template changes.
6. Advert editor with new contact email and pricing template assignment fields.
7. Analytics dashboard showing total views, clicks, CTR and costings by advert.

== Changelog ==

= 1.4.3 =
* Fix: the advertiser pricing-update email used unnumbered placeholders, so a translation could not reorder the advert name, template name, pricing rules and site URL. They are now numbered, which languages with a different word order require.
* Fix: the costings template heading was built with a conditional inside the translation call, so neither "Edit Costings Template" nor "Add New Costings Template" was ever collected for translation. Both are now translatable.
* Internal: added translator comments to the report and pricing-update email strings.

= 1.4.2 =
* Fix: the month shown on monthly advertiser reports could be labelled as the previous month on some sites. The report period is a fixed calendar month, but it was being formatted with the server's runtime timezone applied, which could roll midnight on the 1st backwards. The date is now formatted without a timezone shift, so the label always matches the period being reported.
* Hardening: nonce values are unslashed and sanitized before verification, and the pricing-template admin screens now redirect via wp_safe_redirect().
* Fix: a pricing template whose name contained HTML could render that markup in the adverts list. Template names are now escaped on output.

= 1.4.1 =
* Fix: the advert no longer records a view (or click) when rendered as a preview in the block-based Widgets editor. Previously, opening the Widgets screen could inflate advertiser analytics. Tracking now only fires on genuine front-end page views.

= 1.4.0 =
* Feature: Monthly email reports — advertisers can receive automatic performance summaries
* Feature: Pricing templates — create flexible pricing rules (CPM, CPC, daily/monthly flat rates)
* Feature: Costings integration — assign templates to adverts and include earnings in monthly emails
* Improvement: New "Costings Templates" admin menu to create and manage pricing templates
* Improvement: Advert setup screen now includes optional contact email and pricing template fields
* Improvement: Email logs track all sent reports and earnings snapshots for historical accuracy
* Technical: Added v1.4.0 database tables (email_log, costings_templates) with automatic migration
* Technical: Added FCAD_Cron class for monthly email scheduling via WordPress cron

= 1.3.0 =
* Feature: Multi-select rotating adverts — widgets can now display a random advert from a selection on each page load
* Improvement: Widget form now supports selecting multiple adverts via multi-select input
* Improvement: Backward compatible with existing single-advert widgets (converted automatically on save)
* Tracking for rotating adverts works seamlessly — analytics accumulated per advert regardless of random selection

= 1.2.0 =
* Added: automatic styling for themes that declare support for "fraew-design-tokens" (such as
  the fraew - modern light theme). The advert is framed with the theme's palette and marked
  "Advertisement" via a skin stylesheet, and falls back to neutral default styling under any
  other theme. No theme code required.

= 1.1.0 =
* Fixed: adverts were rendered with a hand-built <img> at full size, so a large image was
  downloaded in full even for a narrow sidebar. Now uses wp_get_attachment_image(), which
  supplies srcset, intrinsic width/height and lazy loading - smaller downloads and no
  layout shift while the advert loads.
* Fixed: adverts scaled down but never up, because the link was display:inline-block and
  the image max-width:100%. Adverts now fill their container at any size.
* Added: --fcad-advert-max-width CSS custom property to cap advert width per widget area.
* Added: fcad_advert_image_size and fcad_advert_image_sizes filters.
* Security: advert links opened with target="_blank" now carry
  rel="noopener nofollow sponsored".

= 1.0.1 =
* Updated plugin metadata and documentation.
* Added step-by-step guidance to the admin screens.
* Fixed a table-creation issue where `CREATE TABLE IF NOT EXISTS` prevented `dbDelta()` from correctly detecting the table name on future schema updates.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.4.1 =
Analytics fix: advert views are no longer counted when the widget is previewed in the block editor, keeping your advertiser reports accurate.

= 1.4.0 =
New features: Monthly email reports and pricing templates. Advertisers can now receive automatic performance summaries with earnings calculations. Create flexible pricing rules (CPM, CPC, flat fees) and assign them to adverts. Fully backward compatible — all new features are optional.

= 1.3.0 =
New feature: Multi-select rotating adverts. Widgets can now randomly display one advert from a selection on each page load. Great for A/B testing different creatives. Fully backward compatible.

= 1.0.1 =
Recommended update: fixes a database table-creation issue and improves in-admin documentation.
