# Cause Marketing for WooCommerce — Developer Reference

This document covers integration points, hooks, CSS classes, and configuration
steps for developers working with or extending the plugin.

---

## Table of Contents

1. [Freemius Activation](#freemius-activation)
2. [PDF Invoice Integration](#pdf-invoice-integration)
3. [Adding Custom Fonts](#adding-custom-fonts)
4. [Front-End CSS Classes](#front-end-css-classes)
5. [Available Filters and Actions](#available-filters-and-actions)
6. [Known Limitations](#known-limitations)
7. [Database Schema](#database-schema)

---

## Freemius Activation

The plugin ships with Freemius integration stubbed out. Until credentials are
added, `CauseMarketing_Pro::is_pro()` returns `true` so all features remain
accessible during development.

**Steps to activate:**

1. Create or log into your account at [freemius.com](https://freemius.com).
2. Add a new product — type: **WordPress Plugin**, model: **Freemium**.
3. Configure pricing: single site, annual + lifetime tiers.
4. From your Freemius dashboard go to **Plugin → Connectivity → SDK Integration**
   and copy your App ID and Public Key.
5. Download the Freemius SDK and place it at:
   ```
   cause-marketing/inc/freemius/
   ```
6. Open `inc/class-cause-freemius.php` and fill in the placeholders:
   ```php
   'id'         => 'REPLACE_WITH_FREEMIUS_APP_ID',
   'public_key' => 'REPLACE_WITH_FREEMIUS_PUBLIC_KEY',
   ```
7. Set the activation flag at the top of the same file:
   ```php
   define( 'CAUSE_MARKETING_FREEMIUS_ENABLED', true );
   ```
8. Update `get_upgrade_url()` in the same file with your real Freemius
   pricing page URL.

**Staging override:**

To force Pro features on a staging or development site without a licence,
add this to `wp-config.php`:

```php
define( 'CAUSE_MARKETING_FORCE_PRO', true );
```

---

## PDF Invoice Integration

### Officially supported plugins

| Plugin | Hook used |
|---|---|
| WooCommerce PDF Invoices & Packing Slips (WP Overnight) | `wpo_wcpdf_after_order_details` |
| WP Midnight PDF | `wpmidnight_pdf_after_order_details` |

Both are detected automatically. No configuration needed.

### Integrating an unsupported PDF plugin

Use the `donation_report_pdf_get_html` filter to retrieve the donation HTML
block for any order:

```php
add_filter( 'your_pdf_plugin_content_filter', function( $html, $order ) {
    $donation_html = apply_filters( 'donation_report_pdf_get_html', '', $order );
    if ( $donation_html ) {
        $html .= $donation_html;
    }
    return $html;
}, 10, 2 );
```

**Return value:** A `<p>` element with inline italic styling, or an empty
string if no donation is recorded on the order.

**Customising the PDF message:**

The message text is configurable in **Display → Messages → PDF Invoice Message**.
It supports `{amount}` and `{cause}` tokens and is limited to 200 characters.
The default message is:

> Thanks to your purchase, we will donate {amount} to {cause}.

---

## Adding Custom Fonts

The font picker on the Display tab is populated automatically from:

- WordPress bundled system fonts (Arial, Georgia, Trebuchet MS, etc.)
- Any Google Font URL enqueued via `wp_enqueue_style()`
- Fonts registered through the WordPress Fonts API (WP 6.0+)
- Fonts defined in an active Elementor Pro kit

To add a font that does not appear automatically, enqueue it in your theme or
a site-specific plugin:

```php
// Google Font example
add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_style(
        'my-custom-font',
        'https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&display=swap',
        array(),
        null
    );
} );

// Also enqueue in the admin so it appears in the picker
add_action( 'admin_enqueue_scripts', function( $hook ) {
    if ( 'woocommerce_page_cause-marketing' !== $hook ) {
        return;
    }
    wp_enqueue_style(
        'my-custom-font',
        'https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&display=swap',
        array(),
        null
    );
} );
```

After adding the enqueue, the font name (e.g. "Playfair Display") will appear
in the Display tab font dropdowns on the next page load.

---

## Front-End CSS Classes

All donation message elements use predictable CSS classes for targeting.

### Product page placements

These placements render as `<em>` elements (italic, centered, inheriting
surrounding styles). They are not styled by the plugin's color/font settings.

| Placement | CSS class |
|---|---|
| Short description | `donation-message-inline` |
| Long description | `donation-message-inline` |
| Product tab | `donation-message-inline` |
| After Add to Cart | `donation-message-inline donation-message--atc` |

### Order-flow placements

These placements render as `<p>` elements and use the plugin's color/font settings.

| Placement | CSS classes |
|---|---|
| Cart total area | `donation-checkout-message donation-cart-total-msg` |
| Checkout order summary | `donation-checkout-message donation-checkout-summary-msg` |
| Thank you page | `donation-checkout-message donation-thankyou-msg` |
| Order email | `donation-checkout-message donation-email-msg` |

### Shortcode output

| Element | CSS class |
|---|---|
| `[cause_message]` wrapper | `donation-report-message` |

### Progress bar elements

| Element | CSS class |
|---|---|
| Outer wrapper | `cause-progress-wrap cause-progress-bar-wrap` |
| Charity name | `cause-progress-charity` |
| Bar track (background) | `cause-progress-bar-track` |
| Bar fill | `cause-progress-bar-fill` |
| Meta row (amounts + %) | `cause-progress-meta` |
| Raised amount | `cause-progress-raised` |
| Goal amount | `cause-progress-goal` |
| Percentage label | `cause-progress-percent` |

Bar colors, track color, border radius, font family, size, and weight are all
controlled via **Display → Progress Bars** and output as inline CSS.

### Customising with CSS

All classes are safe to target in your theme stylesheet:

```css
/* Make the cart donation message bold */
.donation-checkout-message.donation-cart-total-msg {
    font-weight: 700;
}

/* Change progress bar height */
.cause-progress-bar-track {
    height: 24px;
}

/* Style the inline product page message */
.donation-message-inline {
    font-size: 0.9em;
    opacity: 0.85;
}
```

---

## Available Filters and Actions

### `donation_report_pdf_get_html`

Retrieve the donation HTML block for an order. Returns an empty string if
no donation is recorded.

```php
$html = apply_filters( 'donation_report_pdf_get_html', '', $order );
```

**Parameters:**
- `$html` _(string)_ — pass-through value (empty string by default)
- `$order` _(WC_Order)_ — the order to retrieve donation info for

---

### `cause_marketing_fs_loaded`

Fires after the Freemius SDK is initialised (only when
`CAUSE_MARKETING_FREEMIUS_ENABLED` is `true`). Use this to run code that
depends on the Freemius instance.

```php
add_action( 'cause_marketing_fs_loaded', function() {
    $fs = cause_marketing_freemius();
    // $fs->... Freemius SDK calls
} );
```

---

## Known Limitations

### Variation-level charity assignment

Charity assignment operates at the product level, not the variation level.
If a variable product has variations spread across multiple categories, and
those categories have different charity assignments, the resolver will use
whichever matching category it encounters first (non-deterministic).

**Workaround:** Set the charity assignment directly on the parent product
using the **Donation** meta box on the product edit screen. A direct product
assignment always takes precedence over category rules.

Full variation-level charity assignment is a planned future feature.

### Historical orders

The donation ledger (`wp_cause_donations`) is populated only for orders placed
or re-saved after the plugin was installed. Orders from before installation —
including those tracked by a previous version of this plugin — will not appear
in ledger-based reports until a migration utility is run.

If you are migrating from an earlier version, contact support for assistance
with the migration utility.

### Email preview

The monthly email report uses `wp_mail()`. On staging environments, outbound
mail is often blocked at the server level or rejected by SMTP providers due to
domain mismatch. Install a plugin such as **WP Mail Catcher** on staging to
inspect outbound mail without needing real SMTP delivery.

---

## Database Schema

The plugin creates one custom table on activation.

### `{prefix}cause_donations`

Stores one row per order line item per eligible order.

| Column | Type | Description |
|---|---|---|
| `id` | `bigint(20) unsigned` | Auto-increment primary key |
| `order_id` | `bigint(20) unsigned` | WooCommerce order ID |
| `product_id` | `bigint(20) unsigned` | Parent product ID |
| `variation_id` | `bigint(20) unsigned` | Variation ID (0 if not a variation) |
| `charity_id` | `bigint(20) unsigned` | Charity post ID (0 = General Fund) |
| `amount` | `decimal(10,2)` | Donation amount for this line item |
| `status` | `varchar(20)` | `pending`, `confirmed`, or `reversed` |
| `order_date` | `datetime` | Date the order was placed |
| `confirmed_date` | `datetime` | Date the donation was confirmed (NULL if pending) |
| `reversed_date` | `datetime` | Date the donation was reversed (NULL if not reversed) |
| `created_at` | `datetime` | Row creation timestamp |

**Indexes:** `order_id`, `product_id`, `variation_id`, `charity_id`, `status`, `order_date`

### `{prefix}cause_payouts` (Pro)

Stores payout records for charity reconciliation.

| Column | Type | Description |
|---|---|---|
| `id` | `bigint(20) unsigned` | Auto-increment primary key |
| `charity_id` | `bigint(20) unsigned` | Charity post ID (0 = General Fund) |
| `amount` | `decimal(10,2)` | Amount paid |
| `payment_method` | `varchar(100)` | Payment method description |
| `note` | `text` | Optional note |
| `paid_date` | `date` | Date of payment |
| `created_at` | `datetime` | Row creation timestamp |

---

*For support, feature requests, or bug reports, use the plugin support forum
on WordPress.org or the issue tracker on the plugin repository.*
