> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sitestorepro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Building Display Plugins for the Site Store Pro Storefront

> Create built-in or drop-in display plugins that render custom UI blocks anywhere on the storefront using shortcodes and the DisplayPlugin interface.

Display plugins let you inject custom HTML blocks — banners, carousels, promotional widgets, trust badges, or any storefront component — into the page layout via shortcodes. You can ship a plugin as part of the application source (a built-in plugin) or drop it into the root `/plugins/` directory without touching core files (a drop-in plugin). Both approaches implement the same `DisplayPlugin` interface.

## The DisplayPlugin Interface

Every display plugin must implement the following contract:

```php theme={null}
namespace App\Plugins\Contracts;

use App\Models\Plugin;

interface DisplayPlugin
{
    public function slug(): string;
    public function name(): string;
    public function render(array $params, Plugin $plugin): string;
}
```

| Method     | Description                                                        |
| ---------- | ------------------------------------------------------------------ |
| `slug()`   | Unique shortcode identifier used to invoke the plugin in templates |
| `name()`   | Human-readable name shown in the admin plugin list                 |
| `render()` | Returns the HTML string to output at the shortcode location        |

The `$params` array carries any inline shortcode attributes, and the `$plugin` model gives you access to the persisted plugin settings configured in the admin panel.

## Creating a Built-in Plugin

Built-in plugins live inside the application source tree and are registered through the service provider.

<Steps>
  <Step title="Create the Plugin Class">
    Add your class to `app/Plugins/Display/`, implementing `DisplayPlugin`:

    ```php theme={null}
    <?php
    namespace App\Plugins\Display;

    use App\Models\Plugin;
    use App\Plugins\Contracts\DisplayPlugin;

    class MyCustomPlugin implements DisplayPlugin
    {
        public function slug(): string
        {
            return 'my-custom';
        }

        public function name(): string
        {
            return 'My Custom Plugin';
        }

        public function render(array $params, Plugin $plugin): string
        {
            $text = $plugin->getSetting('banner_text', 'Hello, world!');
            return "<div class=\"custom-banner\">{$text}</div>";
        }
    }
    ```
  </Step>

  <Step title="Register in PluginServiceProvider">
    Open `app/Providers/PluginServiceProvider.php` and register your class inside the `boot()` method:

    ```php theme={null}
    $manager->register(\App\Plugins\Display\MyCustomPlugin::class);
    ```
  </Step>

  <Step title="Add the Database Record and Options">
    Add a seeder entry for your plugin in `database/seeders/PluginSeeder.php`, then run:

    ```bash theme={null}
    php artisan db:seed --class=PluginSeeder
    ```

    This inserts the plugin record and its configurable option fields into the `plugins`, `plugin_options`, and `plugin_settings` tables.
  </Step>
</Steps>

## Creating a Drop-in Plugin

Drop-in plugins live in the root `/plugins/` directory and require no changes to application source files. The `PluginManager` discovers them automatically on boot.

<Tip>
  The `PluginManager` scans `/plugins/*/plugin.json` on every boot. As soon as you add a valid plugin directory with a `plugin.json` file, the platform detects it, syncs its settings to the database, and registers its shortcode — no restart or cache clear needed in development.
</Tip>

### Directory Structure

```text theme={null}
plugins/
  my-banner-plugin/
    plugin.json
    MyBannerPlugin.php
```

### plugin.json Schema

The `plugin.json` manifest describes your plugin and declares its configurable options:

```json theme={null}
{
  "class": "MyBannerPlugin",
  "name": "My Banner Plugin",
  "version": "1.0",
  "type": "display",
  "shortcode": "my-banner",
  "description": "Drop-in promotional banner plugin",
  "author": "Store Dev",
  "options": [
    {
      "field_name": "banner_text",
      "field_label": "Banner Text",
      "field_type": "input",
      "field_required": "yes",
      "sort_order": 10,
      "field_default_value": "Welcome to our store!"
    }
  ]
}
```

| Field       | Description                                                       |
| ----------- | ----------------------------------------------------------------- |
| `class`     | PHP class name (without namespace) inside the plugin directory    |
| `type`      | Must be `"display"` for display plugins                           |
| `shortcode` | The tag used to embed the plugin in templates, e.g. `[my-banner]` |
| `options`   | Array of configurable fields exposed in the admin panel           |

### Plugin PHP Class

Place your class file alongside `plugin.json` in the plugin directory:

```php theme={null}
<?php

class MyBannerPlugin implements \App\Plugins\Contracts\DisplayPlugin
{
    public function slug(): string
    {
        return 'my-banner';
    }

    public function name(): string
    {
        return 'My Banner Plugin';
    }

    public function render(array $params, \App\Models\Plugin $plugin): string
    {
        $text = $plugin->getSetting('banner_text', 'Welcome to our store!');
        return "<div class=\"promo-banner\">{$text}</div>";
    }
}
```

## Plugin Model Helper Methods

The `Plugin` model injected into `render()` provides convenience methods for reading and writing plugin settings. All three are available to both built-in and drop-in plugins.

```php theme={null}
// Retrieve a single setting with a fallback default
Plugin::getSetting(string $key, mixed $default): mixed

// Retrieve all settings as a key => value array
Plugin::getSettings(): array

// Persist one or more settings at once
Plugin::saveSettings(array $settings): void
```

**Usage examples:**

```php theme={null}
// Retrieve a single setting with a fallback default
$value = $plugin->getSetting('banner_text', 'Default Text');

// Retrieve all settings as a key => value array
$settings = $plugin->getSettings();

// Persist one or more settings at once
$plugin->saveSettings(['banner_text' => 'New Promo Text']);

// Query all active display plugins
$activeDisplay = Plugin::scopeActive()->scopeOfType('display')->get();
```

## Database Tables

Site Store Pro uses three tables to manage plugin state:

| Table             | Key Columns                                                       | Purpose                              |
| ----------------- | ----------------------------------------------------------------- | ------------------------------------ |
| `plugins`         | `api_id`, `filename`, `type`, `shortcode`, `activation_status`    | Plugin registry and activation state |
| `plugin_options`  | `field_name`, `field_type`, `field_editor`, `field_default_value` | Option field definitions             |
| `plugin_settings` | `field_name`, `field_value`                                       | Persisted admin-configured values    |

***

## Live Search API

Site Store Pro exposes a public JSON endpoint that powers the storefront's real-time search typeahead. You can call this endpoint directly from custom frontend components or headless integrations.

```text theme={null}
GET /api/live-search-api?q={query}
```

| Parameter | Type     | Description                         |
| --------- | -------- | ----------------------------------- |
| `q`       | `string` | The search term entered by the user |

**Example request:**

```text theme={null}
GET /api/live-search-api?q=running+shoes
```

**Example response:**

```json theme={null}
[
  {
    "id": 42,
    "name": "Pro Running Shoes",
    "slug": "pro-running-shoes",
    "price": "89.99",
    "image": "https://cdn.example.com/products/pro-running-shoes.jpg"
  },
  {
    "id": 57,
    "name": "Trail Running Shoes",
    "slug": "trail-running-shoes",
    "price": "109.99",
    "image": "https://cdn.example.com/products/trail-running-shoes.jpg"
  }
]
```

The endpoint searches across product names and returns an array of matching product objects. It is unauthenticated and rate-limited by the standard Laravel throttle middleware. For full-text search configuration options, see [Search & Events](/cms/search-events).
