# Developer hooks

DreamFast Commerce Float exposes filters and actions so you can customize the
widgets from a child theme `functions.php` or a code snippets plugin. You never
need to edit or copy the plugin itself, and your changes survive updates.

All hooks use the `dreamfast_cf_` prefix and were introduced in **1.1.0** unless
noted otherwise.

Hooks marked **Pro** only fire in DreamFast Commerce Float Pro. Everything else
works in both Free and Pro.

**Type safety:** every filter validates the returned value. If a callback
returns the wrong type (for example an array where a string is expected, or an
object from a broken snippet), the plugin silently falls back to the default
value instead of breaking the page:

- visibility filters are cast to boolean;
- `*_args` and `dreamfast_cf_frontend_config` must return an array, otherwise
  the unfiltered array is used;
- text and `*_html` filters must return a string (or another scalar), otherwise
  the default text/markup is used.

---

## Quick reference

| Hook | Type | Purpose |
| --- | --- | --- |
| `dreamfast_cf_show_sticky_cart` | filter | Show/hide the sticky cart bar |
| `dreamfast_cf_show_contact` | filter | Show/hide the contact button |
| `dreamfast_cf_show_coupon` | filter | Show/hide the coupon bar (**Pro**) |
| `dreamfast_cf_sticky_cart_args` | filter | Change sticky bar data before render |
| `dreamfast_cf_contact_args` | filter | Change contact widget data before render |
| `dreamfast_cf_coupon_args` | filter | Change coupon bar data before render (**Pro**) |
| `dreamfast_cf_sticky_cart_button_text` | filter | Primary CTA label |
| `dreamfast_cf_sticky_cart_select_options_text` | filter | "Select options" label |
| `dreamfast_cf_sticky_cart_unavailable_text` | filter | "Unavailable" label |
| `dreamfast_cf_sticky_cart_ask_text` | filter | "Ask about product" label (**Pro**) |
| `dreamfast_cf_sticky_cart_notify_text` | filter | "Notify me" label (**Pro**) |
| `dreamfast_cf_contact_tooltip_text` | filter | Contact button tooltip |
| `dreamfast_cf_sticky_cart_html` | filter | Final sticky bar markup |
| `dreamfast_cf_contact_html` | filter | Final contact button markup |
| `dreamfast_cf_coupon_html` | filter | Final coupon bar markup (**Pro**) |
| `dreamfast_cf_before_sticky_cart` / `dreamfast_cf_after_sticky_cart` | action | Around the sticky bar output |
| `dreamfast_cf_before_contact` / `dreamfast_cf_after_contact` | action | Around the contact button output |
| `dreamfast_cf_before_coupon` / `dreamfast_cf_after_coupon` | action | Around the coupon bar output (**Pro**) |
| `dreamfast_cf_frontend_config` | filter | Data passed to the frontend script |
| `dreamfast_cf_cart_button_selectors` | filter | Selectors for the theme's Add to Cart button (since 1.0.16) |

---

## 1. Visibility

Runs after the plugin's own checks, including the Pro device and category
display rules. Return `false` to hide, `true` to show.

### `dreamfast_cf_show_sticky_cart`

```php
// Hide the sticky cart bar on a specific product.
add_filter( 'dreamfast_cf_show_sticky_cart', function ( $show ) {
	if ( is_product() && get_the_ID() === 123 ) {
		return false;
	}

	return $show;
} );
```

```php
// Show the sticky bar only to logged-out visitors.
add_filter( 'dreamfast_cf_show_sticky_cart', function ( $show ) {
	return $show && ! is_user_logged_in();
} );
```

### `dreamfast_cf_show_contact`

```php
// Hide the contact button outside business hours (store timezone).
add_filter( 'dreamfast_cf_show_contact', function ( $show ) {
	$hour = (int) current_time( 'G' );

	return $show && $hour >= 9 && $hour < 18;
} );
```

### `dreamfast_cf_show_coupon` (Pro)

```php
// Only show the coupon bar to first-time visitors.
add_filter( 'dreamfast_cf_show_coupon', function ( $show ) {
	return $show && ! is_user_logged_in();
} );
```

---

## 2. Data before render

Change the values the template uses, without touching markup.

### `dreamfast_cf_sticky_cart_args`

Parameters: `array $args`, `WC_Product $product`.

| Key | Type | Notes |
| --- | --- | --- |
| `image_url` | string | Thumbnail URL |
| `price_html` | string | Price markup, passed through `wp_kses_post()` |
| `is_purchasable` | bool | Controls which button renders |
| `product_type` | string | `simple`, `variable`, … |
| `out_of_stock_action` | string | **Pro** — `ask`, `back_in_stock`, or empty |
| `ask_url` | string | **Pro** — prefilled WhatsApp URL |

```php
// Use a larger product image in the sticky bar.
add_filter( 'dreamfast_cf_sticky_cart_args', function ( $args, $product ) {
	$image_id = $product->get_image_id();

	if ( $image_id ) {
		$args['image_url'] = wp_get_attachment_image_url( $image_id, 'medium' );
	}

	return $args;
}, 10, 2 );
```

```php
// Append a shipping note to the price shown in the bar.
add_filter( 'dreamfast_cf_sticky_cart_args', function ( $args, $product ) {
	$args['price_html'] .= ' <small>' . esc_html__( 'Free shipping', 'my-theme' ) . '</small>';

	return $args;
}, 10, 2 );
```

### `dreamfast_cf_contact_args`

| Key | Type | Notes |
| --- | --- | --- |
| `position` | string | `bottom-right` or `bottom-left` |
| `whatsapp` | string | Full `wa.me` URL |
| `tooltip_enabled` | bool | |
| `tooltip_text` | string | |
| `channels` | array | **Pro** — active channel keys |
| `phone`, `email`, `waze` | string | **Pro** |
| `is_free_whatsapp_only` | bool | **Pro** — single-channel layout |

```php
// Route wholesale customers to a different WhatsApp number.
add_filter( 'dreamfast_cf_contact_args', function ( $args ) {
	if ( current_user_can( 'wholesale_customer' ) ) {
		$args['whatsapp'] = 'https://wa.me/15551234567';
	}

	return $args;
} );
```

```php
// Move the button to the left on cart and checkout.
add_filter( 'dreamfast_cf_contact_args', function ( $args ) {
	if ( is_cart() || is_checkout() ) {
		$args['position'] = 'bottom-left';
	}

	return $args;
} );
```

### `dreamfast_cf_coupon_args` (Pro)

Keys: `text`, `code`, `position` (`top`/`bottom`), `style` (inline CSS custom properties).

```php
// Swap the coupon code for returning customers.
add_filter( 'dreamfast_cf_coupon_args', function ( $args ) {
	if ( is_user_logged_in() ) {
		$args['text'] = __( 'Welcome back! 15% off', 'my-theme' );
		$args['code'] = 'WELCOMEBACK15';
	}

	return $args;
} );
```

---

## 3. Texts and CTA

Each sticky-bar text filter receives `( $text, $product, $args )` — the label,
the current `WC_Product`, and the same template data array that
`dreamfast_cf_sticky_cart_args` produces. The tooltip filter receives
`( $text, $args )` with the contact widget data. Return a plain string — it is
escaped for you.

```php
// Rename the main CTA.
add_filter( 'dreamfast_cf_sticky_cart_button_text', function ( $text, $product ) {
	return __( 'Buy now', 'my-theme' );
}, 10, 2 );
```

```php
// Product-type-aware CTA.
add_filter( 'dreamfast_cf_sticky_cart_button_text', function ( $text, $product ) {
	if ( $product->is_on_sale() ) {
		return __( 'Grab the deal', 'my-theme' );
	}

	return $text;
}, 10, 2 );
```

```php
// Change the tooltip next to the contact button.
add_filter( 'dreamfast_cf_contact_tooltip_text', function ( $text, $args ) {
	return __( 'Chat with us', 'my-theme' );
}, 10, 2 );
```

Also available: `dreamfast_cf_sticky_cart_select_options_text`,
`dreamfast_cf_sticky_cart_unavailable_text`, and in Pro
`dreamfast_cf_sticky_cart_ask_text` and `dreamfast_cf_sticky_cart_notify_text`.

---

## 4. Markup

### HTML filters

The plugin builds each widget's markup, then passes the finished string through
a filter before printing it.

> **Escaping:** the returned string is printed as-is. The plugin's own markup is
> already escaped; anything **you** add must be escaped by you. Returning an
> empty string suppresses the widget entirely.

```php
// Wrap the sticky bar in your own container.
add_filter( 'dreamfast_cf_sticky_cart_html', function ( $html, $args, $product ) {
	return '<div class="my-sticky-wrapper">' . $html . '</div>';
}, 10, 3 );
```

```php
// Add a trust badge inside the contact widget.
add_filter( 'dreamfast_cf_contact_html', function ( $html, $args ) {
	$badge = '<span class="my-badge">' . esc_html__( 'Replies in ~5 min', 'my-theme' ) . '</span>';

	return $html . $badge;
}, 10, 2 );
```

```php
// Replace the sticky bar markup completely.
add_filter( 'dreamfast_cf_sticky_cart_html', function ( $html, $args, $product ) {
	ob_start();
	?>
	<div id="df-sf-sticky-cart" class="df-sf-sticky-cart df-sf-sticky-cart--bottom">
		<div class="df-sf-sticky-cart__inner">
			<span><?php echo esc_html( $product->get_name() ); ?></span>
			<button type="button" class="df-sf-sticky-cart__btn" data-df-sf-action="add-to-cart">
				<?php esc_html_e( 'Add to cart', 'my-theme' ); ?>
			</button>
		</div>
	</div>
	<?php
	return ob_get_clean();
}, 10, 3 );
```

Keep the `id`, the `df-sf-*` classes, and the `data-df-sf-action` attributes if
you want the bundled CSS and JavaScript to keep working.

### Before / after actions

Fire around the widget output — useful for extra markup, analytics, or
conditionally enqueuing assets.

```php
// Print a promo strip above the sticky bar.
add_action( 'dreamfast_cf_before_sticky_cart', function ( $args, $product ) {
	echo '<div class="my-promo">' . esc_html__( 'Ends tonight', 'my-theme' ) . '</div>';
}, 10, 2 );
```

```php
// Load a custom stylesheet only when the contact button actually renders.
add_action( 'dreamfast_cf_before_contact', function ( $args ) {
	wp_enqueue_style( 'my-contact-tweaks' );
} );
```

Available pairs: `dreamfast_cf_before_sticky_cart` / `dreamfast_cf_after_sticky_cart`,
`dreamfast_cf_before_contact` / `dreamfast_cf_after_contact`, and in Pro
`dreamfast_cf_before_coupon` / `dreamfast_cf_after_coupon`.

---

## 5. Frontend script configuration

### `dreamfast_cf_frontend_config`

Filters the array exposed to JavaScript as `window.dreamfastCfConfig`.

```php
// Add your own flag for custom frontend code.
add_filter( 'dreamfast_cf_frontend_config', function ( $config ) {
	$config['myCustomFlag'] = true;

	return $config;
} );
```

### `dreamfast_cf_cart_button_selectors`

*Since 1.0.16.* The sticky bar appears once the theme's original Add to Cart
button scrolls out of view. If your theme uses non-standard markup, add its
selector here.

```php
add_filter( 'dreamfast_cf_cart_button_selectors', function ( $selectors ) {
	$selectors[] = '.my-theme-add-to-cart';

	return $selectors;
} );
```

Selectors longer than 160 characters, or containing control characters, are
discarded.

---

## Where to put this code

- **Child theme** — `functions.php`
- **Snippets plugin** — a new PHP snippet, set to run everywhere
- **Site-specific plugin** — any file loaded on the frontend

Do not edit the plugin's own files: your changes would be lost on the next
update, and the WordPress.org updater would flag the plugin as modified.
