## Creating a Custom Data Source

This guide walks you through creating a custom data source step-by-step. The process is simple thanks to the base class that handles all registration boilerplate.

### Step 1: Create Your Class File

Create a new PHP file for your custom data source. For this example, we'll create a file called `My_Custom_Data_Source.php` in your theme's functions.php directory or your custom plugin.

    <?php
    /**
     * My Custom Data Source
     *
     * @package My Theme/Plugin
     * @since 1.0.0
     */
    defined( 'ABSPATH' ) || exit;

    class My_Custom_Data_Source extends WPDAI_Custom_Data_Source_Base {

        // Step 2: Set your entity name(s) - array of strings
        protected $entity_names = array( 'my_custom_data' );

        // Step 3: Implement fetch_data() - required
        public function fetch_data( WPDAI_Data_Warehouse $data_warehouse ) {
            // Your implementation here
        }

        // Step 4: Optionally override get_data_mapping() - base returns empty array
        public function get_data_mapping() {
            // Your implementation here (optional)
        }
    }

    // Step 5: Instantiate to register
    new My_Custom_Data_Source();

### Step 2: Set the Entity Name(s)

The `$entity_names` property is the only property you need to set. It is an array of unique identifier(s) for your data source.

    // Single entity:
    protected $entity_names = array( 'my_custom_data' );

    // Multi-entity (one class serving multiple entities):
    protected $entity_names = array( 'orders', 'products', 'customers' );

Requirements:

- Must be unique (not used by built-in entities or other custom sources)
- Should be lowercase
- Use underscores instead of spaces
- Should be descriptive (e.g., 'inventory_tracking', 'third_party_analytics', 'custom_subscriptions')

Do not override `get_entity_name()` or `get_entity_names()`; the base class implements these from `$entity_names`.

Built-in entity names to avoid:

- `orders`, `customers`, `products`, `coupons`, `taxes`, `refunds`
- `subscriptions`, `expenses`, `store_profit`
- `facebook_campaigns`, `google_campaigns`, `analytics`

### Step 3: Implement fetch_data()

The `fetch_data()` method is where you fetch and return your data. It receives a single parameter: the `WPDAI_Data_Warehouse` instance. Get filters and dates from the warehouse (e.g. `$data_warehouse->get_filter( 'date_from' )`, `$data_warehouse->get_date_from()`, `$data_warehouse->get_date_to()`).

    public function fetch_data( WPDAI_Data_Warehouse $data_warehouse ) {
        // Get date range container for proper date alignment
        $date_range_container = $data_warehouse->get_data_by_date_range_container();

        // Get date range from warehouse (not from a $filters parameter)
        $date_from = $data_warehouse->get_date_from();
        $date_to = $data_warehouse->get_date_to();

        // Fetch your data here (database queries, API calls, etc.)
        // ...

        // Return data structure (execution_time and memory_usage are added by the warehouse)
        return array(
            'totals' => array(
                'my_total_metric' => 1234.56,
            ),
            'data_by_date' => array(
                'my_metric_by_date' => $date_range_container,
            ),
            'total_db_records' => 100,
        );
    }

See The fetch_data() Method documentation for detailed information about the return structure and best practices.

### Step 4: Optionally Implement get_data_mapping()

The `get_data_mapping()` method is optional. The base class returns an empty array. Override it only when you need to define how React displays and formats your data (metric labels, types, chart options, etc.).

    public function get_data_mapping() {
        return array(
            'totals' => array(
                'label' => 'My Custom Data',
                'icon' => 'analytics',
                'totals' => array(
                    'my_total_metric' => array(
                        'label' => 'My Total Metric',
                        'type' => 'currency',
                        'format' => 'currency',
                        'description' => 'Total value of my custom metric',
                    ),
                ),
            ),
            'data_by_date' => array(
                'my_metric_by_date' => array(
                    'label' => 'My Metric Over Time',
                    'type' => 'currency',
                    'format' => 'currency',
                    'description' => 'My metric value over time',
                    'chart_calculation' => 'sum',
                ),
            ),
        );
    }

See The get_data_mapping() Method documentation for detailed structure requirements.

### Step 5: Instantiate Your Class

Simply instantiate your class to register it. The base class constructor automatically handles registration via WordPress filters.

    // At the end of your file, or in functions.php if you included it
    new My_Custom_Data_Source();

### Complete Example

Here's a minimal working example:

    <?php
    /**
     * Minimal Custom Data Source Example
     */
    defined( 'ABSPATH' ) || exit;

    class Simple_Custom_Data_Source extends WPDAI_Custom_Data_Source_Base {

        protected $entity_names = array( 'simple_custom' );

        public function fetch_data( WPDAI_Data_Warehouse $data_warehouse ) {
            $date_range_container = $data_warehouse->get_data_by_date_range_container();

            return array(
                'totals' => array(
                    'simple_total' => 500.00,
                ),
                'data_by_date' => array(
                    'simple_by_date' => $date_range_container,
                ),
                'total_db_records' => 1,
            );
        }

        public function get_data_mapping() {
            return array(
                'totals' => array(
                    'label' => 'Simple Custom Data',
                    'icon' => 'analytics',
                    'totals' => array(
                        'simple_total' => array(
                            'label' => 'Simple Total',
                            'type' => 'currency',
                            'format' => 'currency',
                            'description' => 'A simple custom metric',
                        ),
                    ),
                ),
                'data_by_date' => array(
                    'simple_by_date' => array(
                        'label' => 'Simple Over Time',
                        'type' => 'currency',
                        'format' => 'currency',
                        'chart_calculation' => 'sum',
                    ),
                ),
            );
        }
    }

    new Simple_Custom_Data_Source();

### Loading Your File

If your file is not in the auto-loaded extensions folder, you need to include it. Common approaches:

#### Option 1: Include in functions.php

    // In your theme's functions.php
    require_once get_template_directory() . '/includes/my-custom-data-source.php';

#### Option 2: Include in a Plugin

    // In your plugin's main file
    require_once plugin_dir_path( __FILE__ ) . 'includes/my-custom-data-source.php';

#### Option 3: Use WordPress Hook

    // In functions.php
    add_action( 'plugins_loaded', function() {
        require_once get_template_directory() . '/includes/my-custom-data-source.php';
    });

### Verifying Your Data Source

After creating and loading your custom data source:

1. Create or edit a report in Alpha Insights
2. Add a widget (Metric Card, Chart, etc.)
3. In the widget configuration, you should see your entity name in the data source selector
4. Your metrics should appear in the metric selector dropdowns (if you implemented get_data_mapping())

### Next Steps

- Review The fetch_data() Method for detailed data structure requirements
- Review The get_data_mapping() Method for mapping configuration details
- Check out Data Warehouse API Reference for available helper methods
- See Examples for real-world implementation patterns