# Advanced

The ALTCHA WordPress plugin automatically protects your site right after installation, with no extra setup required. This page covers advanced topics and custom integrations for developers and power users who want more control.

## Shortcode

Add the widget manually anywhere shortcodes are supported:

```
[altcha]
```

The shortcode accepts attributes based on the [ALTCHA Widget](/docs/integration/widget/) configuration options:

```
[altcha floating auto="onload"]
```

## Obfuscation

Starting in v2.1.0, the plugin can obfuscate sensitive data — like email addresses and phone numbers — so it's hidden from bots but still usable by real visitors.

```
[obfuscate email="test@example.com" label="Click to reveal"]
```

Supported attributes:

| Attribute | Description |
|---|---|
| `email` | Email address, automatically prefixed with `mailto:`. |
| `tel` | Phone number, automatically prefixed with `tel:`. |
| `text` | Arbitrary text to obfuscate. |
| `label` | Optional placeholder text (defaults to "Click here"). |
| `class` | Optional CSS class names. |
| `obfuscated` | Pre-generated, Base64-encoded obfuscated data, for performance. |

At least one of `email`, `tel`, or `text` is required.

## Custom handlers

For custom form handlers, verify a payload directly using the `AltchaPlugin` class:

```php
$altcha = AltchaPlugin::$instance;
$params = array();
$verified = $altcha->verify($payload, $params);
```

- `$payload` — the base64-encoded ALTCHA payload.
- `$params` — populated automatically with additional parameters.

When using [ALTCHA Sentinel](/docs/sentinel/), the resolved verification data is also available via `$params["verification_data"]`, or as a parsed associative array through `$altcha->verification_data`.

## Hooks

### Actions

**`altcha_verify_result`**

```php
do_action("altcha_verify_result", $verified);
```

Fires after a verification attempt. `$verified` (boolean) indicates whether it succeeded.

### Filters

**`altcha_get_complexity`**

```php
apply_filters("altcha_get_complexity", $result);
```

Overrides the challenge's min/max complexity. Returns an array with `max` and `min` keys.

**`altcha_get_challenge_options`**

```php
apply_filters("altcha_get_challenge_options", $options);
```

Overrides the proof-of-work challenge options (`CreateChallengeOptions` from the PHP library).

**`altcha_get_challenge_url`**

```php
apply_filters("altcha_get_challenge_url", $challenge_url);
```

Overrides the widget's challenge URL.

**`altcha_get_ip_address`**

```php
apply_filters("altcha_get_ip_address", $ip);
```

Overrides the resolved visitor IP address.

**`altcha_get_ip_country`**

```php
apply_filters("altcha_get_ip_country", null, $ip);
```

Overrides the detected country code. By default, `get_ip_country` returns `null`, since no IP-resolution mechanism is bundled with the plugin — use this filter to plug in your own geolocation logic or another plugin's API.

**`altcha_get_settings`**

```php
apply_filters("altcha_get_settings", $settings);
```

Overrides the plugin's settings parameters.

**`altcha_get_widget_attrs`**

```php
apply_filters("altcha_get_widget_attrs", $attrs);
```

Overrides the widget's HTML attributes.

**`altcha_get_widget_html`**

```php
apply_filters("altcha_get_widget_html", $html, $attrs, $wrap);
```

Overrides the widget's rendered HTML. `$html` (string), `$attrs` (array), `$wrap` (boolean).

**`altcha_inject`**

```php
apply_filters("altcha_inject", $inject, $bypass);
```

Returning `false` prevents the ALTCHA scripts from being added to the page. `$inject` (bool), `$bypass` (bool — true if the current user/IP/cookie already bypasses verification). See [Controlling where scripts are injected](#controlling-where-scripts-are-injected) below for a full example.

**`altcha_intercept`**

```php
apply_filters("altcha_intercept", $intercept, $payload_data, $params);
```

Returning `false` disables interception, so verification isn't required for that request. `$intercept` (boolean), `$payload_data` (array), `$params` (array).

## Plugin integrations

Thanks to the request interceptor, ALTCHA works automatically with most form plugins — no setup required. The widget displays as an overlay, or stays fully invisible in the background, depending on your configuration.

Tested plugins:

- CoBlocks
- Contact Form 7
- Divi
- Elementor Pro
- EventPrime
- Everest Forms
- Fluent Forms
- Formidable Forms
- Forminator
- Gravity Forms
- HTML Forms
- Kali Forms
- MailPoet
- Newsletter
- Noptin
- Ninja Forms
- Sure Forms
- WooCommerce
- wpDiscuz
- WPForms
- WP-Members
- User Registration
- WordPress Comments
- WordPress Login, Register, and Password Reset

If a plugin isn't recognized automatically, see [Enabling ALTCHA for certain plugins](#enabling-altcha-for-certain-plugins) below.

## Country detection

The plugin determines a visitor's country from their timezone, as reported during verification. This provides reliable, privacy-friendly geolocation without depending on any IP-address resolution service.

Country is used for event logging and for firewall request blocking. For more precise geolocation, use the [`altcha_get_ip_country`](#filters) filter to plug in your own IP-based resolution logic.

## Cookies and GDPR

The plugin uses only strictly necessary, first-party cookies required for the security mechanisms to work. No personally identifiable information (PII) is stored or processed through these cookies — consistent with the legitimate-interest basis under **Article 6(1)(f) GDPR** (security, integrity, and reliable operation).

**Essential security cookie:**

- `altcha` — a single-use, transient functional cookie for validating form submissions and preventing spam. Contains no personal data.

**Temporary protection cookies** (Under Attack Mode only):

- `altcha_under_attack` — session-based access management during malicious activity.
- `altcha_under_attack_expires` — records the expiration timestamp.
- `altcha_under_attack_ttl` — records the cookie's lifespan (time-to-live).
- `altcha_under_attack_tz` — stores the visitor's timezone, for low-precision country detection.

All of these cookies are:

- First-party, stored only on the visitor's device by your site's domain.
- Strictly necessary for the site's security and operation.
- Temporary, expiring automatically once their purpose is fulfilled.
- Free of any personal or behavioral data.
- Exempt from consent requirements under **Article 5(3) of the ePrivacy Directive** (Directive 2002/58/EC).

## API caching

The plugin fetches challenges from:

```
/wp-json/altcha/v1/challenge
```

**This endpoint must be excluded from caching** by any CDN or caching plugin — it must return a fresh challenge on every request. Some hosting providers strip or ignore cookies by default; make sure the `altcha` cookie is excluded from caching too.

### Under Attack Mode with a CDN

Most CDN providers already offer DDoS protection or rate limiting at the edge, which makes the plugin's [Under Attack Mode](/docs/wordpress/features/#under-attack-mode) generally unnecessary on top of that.

**WP Engine:** exclude these cookies from caching:

- `altcha_under_attack`
- `altcha_under_attack_tz`

Note that excluding these cookies causes WP Engine to bypass caching entirely for affected requests — for that reason, **Under Attack Mode is not recommended on WP Engine**.

**Other providers:** most CDNs and proxies that follow standard caching behavior and respect `Cache-Control` headers need no additional configuration.

## How To

### Enabling ALTCHA for certain plugins

If a plugin isn't in the [tested list](#plugin-integrations) above, you can still protect its forms by adding its AJAX paths or actions in **Settings**:

- **REST API endpoints** — add the specific path (e.g. `/wp-json/some-plugin/submit`) to the Paths setting, or use a wildcard (e.g. `/wp-json/some-plugin/*`) to cover all of that plugin's requests.
- **`admin-ajax.php` requests** — add the AJAX action name to the Actions setting (e.g. `action_name`).

### Controlling where scripts are injected

By default, the widget scripts load on every page. To reduce overhead, you can limit injection to only the pages that need protection, using either approach:

**Option 1 — Paths setting**

Add specific paths to inject on, e.g. `/contact` and `/shop/*`. Remove the default `*` wildcard first, or the scripts will keep loading everywhere.

**Option 2 — the `altcha_inject` filter**

Use the [`altcha_inject`](#filters) filter for programmatic control — for example, injecting only on a contact page, a shop section, and the WordPress login page when login protection is enabled:

```php
add_filter('altcha_inject', function ($inject, $bypass) {
if ($bypass) {
    return $inject;
}

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path === '/contact' || str_starts_with($path, '/shop/')) {
    return true;
}

if (str_contains($path, 'wp-login.php')) {
    return true;
}

return false;
}, 10, 2);
```

## Next steps

- **[Troubleshooting](/docs/wordpress/troubleshooting/)** — diagnose issues with verification, caching, or specific plugins.
- **[Releases](/docs/wordpress/releases/)** — version history and changelog.
