Add Multi-Currency Support to WordPress & WooCommerce with Official RBA Exchange Rates API

Build professional currency conversion features for WordPress and WooCommerce using official Reserve Bank of Australia exchange rate data. Includes shortcodes, WooCommerce integration, and admin settings you can deploy immediately.

WordPress powers 40% of the web, and many Australian businesses need accurate currency conversion for international customers. Using official Reserve Bank of Australia exchange rate data, we'll build professional currency features that integrate seamlessly with WordPress and WooCommerce.

What We're Building

  • WordPress plugin with admin settings
  • Currency converter shortcode for any page/post
  • WooCommerce integration for multi-currency pricing
  • Automatic daily rate updates via cron
  • Cache system for optimal performance
  • Admin dashboard for rate management

Plugin Structure

Create a new plugin directory in /wp-content/plugins/rba-currency-converter/:

Building non-WordPress applications? Check out our Python backend tutorial for command-line and Flask implementations, or our React frontend tutorial for modern web apps.

rba-currency-converter/
├── rba-currency-converter.php (main plugin file)
├── includes/
│   ├── class-api-client.php
│   ├── class-admin.php
│   ├── class-shortcodes.php
│   └── class-woocommerce.php
├── assets/
│   ├── admin.css
│   ├── frontend.css
│   └── frontend.js
└── templates/
    └── converter-widget.php

Main Plugin File

<?php
/**
 * Plugin Name: RBA Currency Converter
 * Description: Professional currency conversion using official Reserve Bank of Australia exchange rates
 * Version: 1.0.0
 * Author: Your Name
 * Requires at least: 5.0
 * Tested up to: 6.4
 * Requires PHP: 7.4
 * License: GPL v2 or later
 * Text Domain: rba-currency
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Plugin constants
define('RBA_CURRENCY_PLUGIN_URL', plugin_dir_url(__FILE__));
define('RBA_CURRENCY_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('RBA_CURRENCY_VERSION', '1.0.0');

class RBA_Currency_Converter {
    
    public function __construct() {
        add_action('init', array($this, 'init'));
        add_action('plugins_loaded', array($this, 'load_textdomain'));
        
        // Activation/deactivation hooks
        register_activation_hook(__FILE__, array($this, 'activate'));
        register_deactivation_hook(__FILE__, array($this, 'deactivate'));
    }
    
    public function init() {
        // Load includes
        $this->load_includes();
        
        // Initialize components
        new RBA_Currency_API_Client();
        new RBA_Currency_Admin();
        new RBA_Currency_Shortcodes();
        
        // Initialize WooCommerce integration if active
        if (class_exists('WooCommerce')) {
            new RBA_Currency_WooCommerce();
        }
        
        // Enqueue scripts and styles
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
        
        // Schedule daily rate updates
        if (!wp_next_scheduled('rba_currency_daily_update')) {
            wp_schedule_event(time(), 'daily', 'rba_currency_daily_update');
        }
        add_action('rba_currency_daily_update', array($this, 'update_daily_rates'));
    }
    
    public function load_includes() {
        require_once RBA_CURRENCY_PLUGIN_PATH . 'includes/class-api-client.php';
        require_once RBA_CURRENCY_PLUGIN_PATH . 'includes/class-admin.php';
        require_once RBA_CURRENCY_PLUGIN_PATH . 'includes/class-shortcodes.php';
        
        if (class_exists('WooCommerce')) {
            require_once RBA_CURRENCY_PLUGIN_PATH . 'includes/class-woocommerce.php';
        }
    }
    
    public function enqueue_frontend_assets() {
        wp_enqueue_style(
            'rba-currency-frontend',
            RBA_CURRENCY_PLUGIN_URL . 'assets/frontend.css',
            array(),
            RBA_CURRENCY_VERSION
        );
        
        wp_enqueue_script(
            'rba-currency-frontend',
            RBA_CURRENCY_PLUGIN_URL . 'assets/frontend.js',
            array('jquery'),
            RBA_CURRENCY_VERSION,
            true
        );
        
        // Localize script for AJAX
        wp_localize_script('rba-currency-frontend', 'rba_currency_ajax', array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('rba_currency_nonce')
        ));
    }
    
    public function enqueue_admin_assets($hook) {
        if (strpos($hook, 'rba-currency') !== false) {
            wp_enqueue_style(
                'rba-currency-admin',
                RBA_CURRENCY_PLUGIN_URL . 'assets/admin.css',
                array(),
                RBA_CURRENCY_VERSION
            );
        }
    }
    
    public function activate() {
        // Create necessary database tables
        $this->create_tables();
        
        // Set default options
        add_option('rba_currency_api_key', '');
        add_option('rba_currency_default_from', 'AUD');
        add_option('rba_currency_default_to', 'USD');
        add_option('rba_currency_cache_duration', 300); // 5 minutes
        add_option('rba_currency_decimal_places', 2);
        
        // Schedule daily updates
        if (!wp_next_scheduled('rba_currency_daily_update')) {
            wp_schedule_event(time(), 'daily', 'rba_currency_daily_update');
        }
    }
    
    public function deactivate() {
        // Clear scheduled events
        wp_clear_scheduled_hook('rba_currency_daily_update');
    }
    
    public function create_tables() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'rba_currency_rates';
        
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE $table_name (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            rate_date date NOT NULL,
            currency_code varchar(3) NOT NULL,
            rate decimal(10,6) NOT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY unique_rate (rate_date, currency_code),
            KEY idx_date (rate_date),
            KEY idx_currency (currency_code)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
    }
    
    public function load_textdomain() {
        load_plugin_textdomain('rba-currency', false, dirname(plugin_basename(__FILE__)) . '/languages');
    }
    
    public function update_daily_rates() {
        $api_client = new RBA_Currency_API_Client();
        $api_client->update_latest_rates();
    }
}

// Initialize the plugin
new RBA_Currency_Converter();

API Client Class

<?php
// includes/class-api-client.php

class RBA_Currency_API_Client {
    
    private $api_base = 'https://api.exchangeratesapi.com.au';
    private $api_key;
    
    public function __construct() {
        $this->api_key = get_option('rba_currency_api_key', '');
        
        // AJAX actions for frontend
        add_action('wp_ajax_rba_convert_currency', array($this, 'ajax_convert_currency'));
        add_action('wp_ajax_nopriv_rba_convert_currency', array($this, 'ajax_convert_currency'));
        add_action('wp_ajax_rba_get_rates', array($this, 'ajax_get_rates'));
        add_action('wp_ajax_nopriv_rba_get_rates', array($this, 'ajax_get_rates'));
    }
    
    public function get_headers() {
        return array(
            'Authorization' => 'Bearer ' . $this->api_key,
            'User-Agent' => 'WordPress-RBA-Currency-Plugin/' . RBA_CURRENCY_VERSION
        );
    }
    
    public function get_latest_rates($from_cache = true) {
        if ($from_cache) {
            $cached_rates = get_transient('rba_currency_latest_rates');
            if ($cached_rates !== false) {
                return $cached_rates;
            }
        }
        
        $response = wp_remote_get(
            $this->api_base . '/latest',
            array(
                'headers' => $this->get_headers(),
                'timeout' => 15
            )
        );
        
        if (is_wp_error($response)) {
            return new WP_Error('api_error', $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (!isset($data['success']) || !$data['success']) {
            return new WP_Error('api_error', $data['error']['info'] ?? 'Unknown API error');
        }
        
        // Cache the results
        $cache_duration = get_option('rba_currency_cache_duration', 300);
        set_transient('rba_currency_latest_rates', $data, $cache_duration);
        
        return $data;
    }
    
    public function convert_currency($from, $to, $amount, $date = null) {
        $cache_key = "rba_convert_{$from}_{$to}_{$amount}_" . ($date ?: 'latest');
        $cached_result = get_transient($cache_key);
        
        if ($cached_result !== false) {
            return $cached_result;
        }
        
        $url = $this->api_base . '/convert';
        $params = array(
            'from' => $from,
            'to' => $to,
            'amount' => $amount
        );
        
        if ($date) {
            $params['date'] = $date;
        }
        
        $response = wp_remote_get(
            add_query_arg($params, $url),
            array(
                'headers' => $this->get_headers(),
                'timeout' => 15
            )
        );
        
        if (is_wp_error($response)) {
            return new WP_Error('api_error', $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (!isset($data['success']) || !$data['success']) {
            return new WP_Error('api_error', $data['error']['info'] ?? 'Unknown API error');
        }
        
        // Cache the result
        set_transient($cache_key, $data, 300); // 5 minutes
        
        return $data;
    }
    
    public function get_historical_rates($date) {
        $cache_key = "rba_historical_{$date}";
        $cached_result = get_transient($cache_key);
        
        if ($cached_result !== false) {
            return $cached_result;
        }
        
        $response = wp_remote_get(
            $this->api_base . '/' . $date,
            array(
                'headers' => $this->get_headers(),
                'timeout' => 15
            )
        );
        
        if (is_wp_error($response)) {
            return new WP_Error('api_error', $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);
        
        if (!isset($data['success']) || !$data['success']) {
            return new WP_Error('api_error', $data['error']['info'] ?? 'Unknown API error');
        }
        
        // Cache historical data for 24 hours (it doesn't change)
        set_transient($cache_key, $data, DAY_IN_SECONDS);
        
        return $data;
    }
    
    public function update_latest_rates() {
        global $wpdb;
        
        $rates_data = $this->get_latest_rates(false); // Force fresh data
        
        if (is_wp_error($rates_data)) {
            error_log('RBA Currency: Failed to update rates - ' . $rates_data->get_error_message());
            return false;
        }
        
        $table_name = $wpdb->prefix . 'rba_currency_rates';
        $rate_date = $rates_data['date'];
        
        // Insert or update rates
        foreach ($rates_data['rates'] as $currency => $rate) {
            $wpdb->replace(
                $table_name,
                array(
                    'rate_date' => $rate_date,
                    'currency_code' => $currency,
                    'rate' => $rate
                ),
                array('%s', '%s', '%f')
            );
        }
        
        return true;
    }
    
    public function ajax_convert_currency() {
        check_ajax_referer('rba_currency_nonce', 'nonce');
        
        $from = sanitize_text_field($_POST['from'] ?? '');
        $to = sanitize_text_field($_POST['to'] ?? '');
        $amount = floatval($_POST['amount'] ?? 0);
        $date = sanitize_text_field($_POST['date'] ?? '');
        
        if (empty($from) || empty($to) || $amount <= 0) {
            wp_send_json_error('Invalid parameters');
        }
        
        $result = $this->convert_currency($from, $to, $amount, $date ?: null);
        
        if (is_wp_error($result)) {
            wp_send_json_error($result->get_error_message());
        }
        
        wp_send_json_success($result);
    }
    
    public function ajax_get_rates() {
        check_ajax_referer('rba_currency_nonce', 'nonce');
        
        $rates = $this->get_latest_rates();
        
        if (is_wp_error($rates)) {
            wp_send_json_error($rates->get_error_message());
        }
        
        wp_send_json_success($rates);
    }
}

Shortcodes Class

<?php
// includes/class-shortcodes.php

class RBA_Currency_Shortcodes {
    
    public function __construct() {
        add_shortcode('rba_currency_converter', array($this, 'currency_converter_shortcode'));
        add_shortcode('rba_currency_rate', array($this, 'currency_rate_shortcode'));
        add_shortcode('rba_currency_convert', array($this, 'currency_convert_shortcode'));
    }
    
    /**
     * Full currency converter widget
     * Usage: [rba_currency_converter]
     * Usage: [rba_currency_converter from="AUD" to="USD" amount="100"]
     */
    public function currency_converter_shortcode($atts) {
        $atts = shortcode_atts(array(
            'from' => get_option('rba_currency_default_from', 'AUD'),
            'to' => get_option('rba_currency_default_to', 'USD'),
            'amount' => '100',
            'show_historical' => 'true',
            'show_rates_grid' => 'true',
            'width' => '100%',
            'theme' => 'default'
        ), $atts);
        
        ob_start();
        ?>
        <div class="rba-currency-converter" data-theme="<?php echo esc_attr($atts['theme']); ?>" style="width: <?php echo esc_attr($atts['width']); ?>;">
            <div class="converter-header">
                <h3><?php _e('Currency Converter', 'rba-currency'); ?></h3>
                <p class="converter-subtitle"><?php _e('Official RBA Exchange Rates', 'rba-currency'); ?></p>
            </div>
            
            <form class="converter-form" id="rba-converter-form">
                <div class="form-row">
                    <div class="form-group">
                        <label for="amount"><?php _e('Amount', 'rba-currency'); ?></label>
                        <input type="number" id="amount" name="amount" value="<?php echo esc_attr($atts['amount']); ?>" step="0.01" min="0" />
                    </div>
                </div>
                
                <div class="form-row currency-row">
                    <div class="form-group">
                        <label for="from-currency"><?php _e('From', 'rba-currency'); ?></label>
                        <select id="from-currency" name="from">
                            <?php echo $this->get_currency_options($atts['from']); ?>
                        </select>
                    </div>
                    
                    <button type="button" class="swap-currencies" title="<?php _e('Swap currencies', 'rba-currency'); ?>">
                        ⇄
                    </button>
                    
                    <div class="form-group">
                        <label for="to-currency"><?php _e('To', 'rba-currency'); ?></label>
                        <select id="to-currency" name="to">
                            <?php echo $this->get_currency_options($atts['to']); ?>
                        </select>
                    </div>
                </div>
                
                <?php if ($atts['show_historical'] === 'true'): ?>
                <div class="form-row historical-row" style="display: none;">
                    <div class="form-group">
                        <label for="historical-date"><?php _e('Historical Date (optional)', 'rba-currency'); ?></label>
                        <input type="date" id="historical-date" name="date" min="2018-01-01" max="<?php echo date('Y-m-d'); ?>" />
                    </div>
                    <button type="button" class="toggle-historical"><?php _e('Use Historical Rate', 'rba-currency'); ?></button>
                </div>
                <?php endif; ?>
                
                <button type="submit" class="convert-button">
                    <span class="button-text"><?php _e('Convert', 'rba-currency'); ?></span>
                    <span class="loading-spinner" style="display: none;">⏳</span>
                </button>
            </form>
            
            <div class="conversion-result" id="conversion-result" style="display: none;">
                <div class="result-amount"></div>
                <div class="result-details"></div>
            </div>
            
            <?php if ($atts['show_rates_grid'] === 'true'): ?>
            <div class="rates-grid" id="rates-grid">
                <h4><?php _e('Current Exchange Rates', 'rba-currency'); ?></h4>
                <div class="rates-container"></div>
            </div>
            <?php endif; ?>
            
            <div class="converter-footer">
                <small><?php _e('Data sourced from Reserve Bank of Australia', 'rba-currency'); ?></small>
            </div>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            const converter = new RBACurrencyConverter('#rba-converter-form');
        });
        </script>
        <?php
        
        return ob_get_clean();
    }
    
    /**
     * Display a single exchange rate
     * Usage: [rba_currency_rate from="AUD" to="USD"]
     */
    public function currency_rate_shortcode($atts) {
        $atts = shortcode_atts(array(
            'from' => 'AUD',
            'to' => 'USD',
            'decimals' => get_option('rba_currency_decimal_places', 4),
            'format' => 'rate' // 'rate' or 'full'
        ), $atts);
        
        $api_client = new RBA_Currency_API_Client();
        $rates_data = $api_client->get_latest_rates();
        
        if (is_wp_error($rates_data)) {
            return '<span class="rba-currency-error">Rate unavailable</span>';
        }
        
        $rate = $rates_data['rates'][$atts['to']] ?? null;
        
        if (!$rate) {
            return '<span class="rba-currency-error">Currency not supported</span>';
        }
        
        $formatted_rate = number_format($rate, $atts['decimals']);
        
        if ($atts['format'] === 'full') {
            return "<span class=\"rba-currency-rate\">1 {$atts['from']} = {$formatted_rate} {$atts['to']}</span>";
        }
        
        return "<span class=\"rba-currency-rate\">{$formatted_rate}</span>";
    }
    
    /**
     * Convert and display a specific amount
     * Usage: [rba_currency_convert from="AUD" to="USD" amount="100"]
     */
    public function currency_convert_shortcode($atts) {
        $atts = shortcode_atts(array(
            'from' => 'AUD',
            'to' => 'USD',
            'amount' => '100',
            'decimals' => get_option('rba_currency_decimal_places', 2),
            'show_calculation' => 'false'
        ), $atts);
        
        $api_client = new RBA_Currency_API_Client();
        $result = $api_client->convert_currency($atts['from'], $atts['to'], $atts['amount']);
        
        if (is_wp_error($result)) {
            return '<span class="rba-currency-error">Conversion unavailable</span>';
        }
        
        $converted_amount = number_format($result['result'], $atts['decimals']);
        
        if ($atts['show_calculation'] === 'true') {
            $rate = number_format($result['info']['rate'], 6);
            return "<span class=\"rba-currency-convert\">{$atts['amount']} {$atts['from']} = {$converted_amount} {$atts['to']} <small>(Rate: {$rate})</small></span>";
        }
        
        return "<span class=\"rba-currency-convert\">{$converted_amount} {$atts['to']}</span>";
    }
    
    private function get_currency_options($selected = '') {
        $currencies = array(
            'AUD' => 'Australian Dollar',
            'USD' => 'US Dollar',
            'EUR' => 'Euro',
            'GBP' => 'British Pound',
            'JPY' => 'Japanese Yen',
            'CAD' => 'Canadian Dollar',
            'CHF' => 'Swiss Franc',
            'CNY' => 'Chinese Renminbi',
            'NZD' => 'New Zealand Dollar',
            'SGD' => 'Singapore Dollar',
            'HKD' => 'Hong Kong Dollar',
            'KRW' => 'South Korean Won',
            'INR' => 'Indian Rupee',
            'THB' => 'Thai Baht',
            'MYR' => 'Malaysian Ringgit',
            'IDR' => 'Indonesian Rupiah',
            'VND' => 'Vietnamese Dong',
            'PHP' => 'Philippine Peso',
            'TWD' => 'Taiwan New Dollar'
        );
        
        $options = '';
        foreach ($currencies as $code => $name) {
            $selected_attr = ($code === $selected) ? 'selected' : '';
            $options .= "<option value=\"{$code}\" {$selected_attr}>{$code} - {$name}</option>";
        }
        
        return $options;
    }
}

WooCommerce Integration

<?php
// includes/class-woocommerce.php

class RBA_Currency_WooCommerce {
    
    public function __construct() {
        // Add currency switcher to shop
        add_action('woocommerce_before_shop_loop', array($this, 'add_currency_switcher'));
        
        // Convert prices on display
        add_filter('woocommerce_get_price_html', array($this, 'convert_price_display'), 10, 2);
        
        // Add currency info to checkout
        add_action('woocommerce_review_order_before_payment', array($this, 'add_currency_notice'));
        
        // Admin settings
        add_filter('woocommerce_get_settings_general', array($this, 'add_woocommerce_settings'), 10, 2);
    }
    
    public function add_currency_switcher() {
        if (!get_option('rba_currency_woo_show_switcher', false)) {
            return;
        }
        
        $selected_currency = $this->get_selected_currency();
        
        ?>
        <div class="rba-currency-switcher woocommerce-currency-switcher">
            <label for="currency-selector"><?php _e('View prices in:', 'rba-currency'); ?></label>
            <select id="currency-selector" name="display_currency">
                <option value="AUD" <?php selected($selected_currency, 'AUD'); ?>>AUD - Australian Dollar</option>
                <option value="USD" <?php selected($selected_currency, 'USD'); ?>>USD - US Dollar</option>
                <option value="EUR" <?php selected($selected_currency, 'EUR'); ?>>EUR - Euro</option>
                <option value="GBP" <?php selected($selected_currency, 'GBP'); ?>>GBP - British Pound</option>
            </select>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            $('#currency-selector').on('change', function() {
                const currency = $(this).val();
                document.cookie = `rba_display_currency=${currency}; path=/; max-age=86400`;
                location.reload();
            });
        });
        </script>
        <?php
    }
    
    public function convert_price_display($price_html, $product) {
        if (!get_option('rba_currency_woo_convert_prices', false)) {
            return $price_html;
        }
        
        $display_currency = $this->get_selected_currency();
        
        if ($display_currency === 'AUD') {
            return $price_html;
        }
        
        // Extract price from HTML
        preg_match_all('/[\d,]+\.?\d*/', $price_html, $matches);
        
        if (empty($matches[0])) {
            return $price_html;
        }
        
        $api_client = new RBA_Currency_API_Client();
        
        foreach ($matches[0] as $price_text) {
            $price = floatval(str_replace(',', '', $price_text));
            
            if ($price > 0) {
                $converted = $api_client->convert_currency('AUD', $display_currency, $price);
                
                if (!is_wp_error($converted)) {
                    $converted_price = $this->format_price($converted['result'], $display_currency);
                    $price_html = str_replace($price_text, $converted_price, $price_html);
                }
            }
        }
        
        // Add currency notice
        $price_html .= " <small class=\"currency-notice\">({$display_currency})</small>";
        
        return $price_html;
    }
    
    public function add_currency_notice() {
        $display_currency = $this->get_selected_currency();
        
        if ($display_currency !== 'AUD') {
            echo '<div class="woocommerce-info">';
            echo '<p>' . sprintf(
                __('Prices shown in %s for reference only. You will be charged in AUD at checkout.', 'rba-currency'),
                $display_currency
            ) . '</p>';
            echo '</div>';
        }
    }
    
    private function get_selected_currency() {
        return $_COOKIE['rba_display_currency'] ?? 'AUD';
    }
    
    private function format_price($amount, $currency) {
        $symbol = $this->get_currency_symbol($currency);
        return $symbol . number_format($amount, 2);
    }
    
    private function get_currency_symbol($currency) {
        $symbols = array(
            'AUD' => '$',
            'USD' => '$',
            'EUR' => '€',
            'GBP' => '£',
            'JPY' => '¥',
            'CAD' => 'C$',
            'CHF' => 'CHF',
            'CNY' => '¥'
        );
        
        return $symbols[$currency] ?? $currency . ' ';
    }
    
    public function add_woocommerce_settings($settings, $current_section) {
        if ($current_section === '') {
            $rba_settings = array(
                array(
                    'title' => __('RBA Currency Converter', 'rba-currency'),
                    'type' => 'title',
                    'desc' => __('Settings for RBA Currency Converter integration', 'rba-currency'),
                    'id' => 'rba_currency_woo_options'
                ),
                array(
                    'title' => __('Show Currency Switcher', 'rba-currency'),
                    'desc' => __('Display currency switcher on shop pages', 'rba-currency'),
                    'id' => 'rba_currency_woo_show_switcher',
                    'default' => 'no',
                    'type' => 'checkbox'
                ),
                array(
                    'title' => __('Convert Price Display', 'rba-currency'),
                    'desc' => __('Show converted prices in selected currency', 'rba-currency'),
                    'id' => 'rba_currency_woo_convert_prices',
                    'default' => 'no',
                    'type' => 'checkbox'
                ),
                array(
                    'type' => 'sectionend',
                    'id' => 'rba_currency_woo_options'
                )
            );
            
            $settings = array_merge($settings, $rba_settings);
        }
        
        return $settings;
    }
}

Frontend JavaScript

For a more modern approach with React components and hooks, see our React currency converter tutorial.

// assets/frontend.js

class RBACurrencyConverter {
    constructor(formSelector) {
        this.form = document.querySelector(formSelector);
        this.initializeEventListeners();
        this.loadCurrentRates();
    }
    
    initializeEventListeners() {
        if (!this.form) return;
        
        this.form.addEventListener('submit', this.handleConversion.bind(this));
        
        const swapButton = this.form.querySelector('.swap-currencies');
        if (swapButton) {
            swapButton.addEventListener('click', this.swapCurrencies.bind(this));
        }
        
        const historicalToggle = this.form.querySelector('.toggle-historical');
        if (historicalToggle) {
            historicalToggle.addEventListener('click', this.toggleHistorical.bind(this));
        }
    }
    
    async handleConversion(e) {
        e.preventDefault();
        
        const formData = new FormData(this.form);
        const data = {
            action: 'rba_convert_currency',
            nonce: rba_currency_ajax.nonce,
            from: formData.get('from'),
            to: formData.get('to'),
            amount: formData.get('amount'),
            date: formData.get('date')
        };
        
        this.setLoading(true);
        
        try {
            const response = await fetch(rba_currency_ajax.ajax_url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams(data)
            });
            
            const result = await response.json();
            
            if (result.success) {
                this.displayResult(result.data);
            } else {
                this.displayError(result.data);
            }
        } catch (error) {
            this.displayError('Network error occurred');
        } finally {
            this.setLoading(false);
        }
    }
    
    swapCurrencies() {
        const fromSelect = this.form.querySelector('#from-currency');
        const toSelect = this.form.querySelector('#to-currency');
        
        const temp = fromSelect.value;
        fromSelect.value = toSelect.value;
        toSelect.value = temp;
    }
    
    toggleHistorical() {
        const historicalRow = this.form.querySelector('.historical-row');
        const toggleButton = this.form.querySelector('.toggle-historical');
        
        if (historicalRow.style.display === 'none') {
            historicalRow.style.display = 'block';
            toggleButton.textContent = 'Use Current Rate';
        } else {
            historicalRow.style.display = 'none';
            toggleButton.textContent = 'Use Historical Rate';
            this.form.querySelector('#historical-date').value = '';
        }
    }
    
    displayResult(data) {
        const resultDiv = document.getElementById('conversion-result');
        const amountDiv = resultDiv.querySelector('.result-amount');
        const detailsDiv = resultDiv.querySelector('.result-details');
        
        amountDiv.innerHTML = `${data.query.amount} ${data.query.from} = ${this.formatNumber(data.result)} ${data.query.to}`;
        detailsDiv.innerHTML = `
            <div>Exchange Rate: 1 ${data.query.from} = ${data.info.rate.toFixed(6)} ${data.query.to}</div>
            <div>Rate Date: ${data.date}</div>
        `;
        
        resultDiv.style.display = 'block';
    }
    
    displayError(message) {
        const resultDiv = document.getElementById('conversion-result');
        resultDiv.innerHTML = `<div class="error">Error: ${message}</div>`;
        resultDiv.style.display = 'block';
    }
    
    setLoading(isLoading) {
        const button = this.form.querySelector('.convert-button');
        const buttonText = button.querySelector('.button-text');
        const spinner = button.querySelector('.loading-spinner');
        
        if (isLoading) {
            buttonText.style.display = 'none';
            spinner.style.display = 'inline';
            button.disabled = true;
        } else {
            buttonText.style.display = 'inline';
            spinner.style.display = 'none';
            button.disabled = false;
        }
    }
    
    async loadCurrentRates() {
        const ratesGrid = document.getElementById('rates-grid');
        if (!ratesGrid) return;
        
        const container = ratesGrid.querySelector('.rates-container');
        
        try {
            const response = await fetch(rba_currency_ajax.ajax_url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    action: 'rba_get_rates',
                    nonce: rba_currency_ajax.nonce
                })
            });
            
            const result = await response.json();
            
            if (result.success) {
                this.displayRatesGrid(result.data.rates, container);
            }
        } catch (error) {
            console.log('Failed to load current rates');
        }
    }
    
    displayRatesGrid(rates, container) {
        const majorCurrencies = ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'CHF'];
        let html = '';
        
        majorCurrencies.forEach(currency => {
            if (rates[currency]) {
                html += `
                    <div class="rate-item">
                        <span class="currency-code">${currency}</span>
                        <span class="rate-value">${this.formatNumber(rates[currency], 4)}</span>
                    </div>
                `;
            }
        });
        
        container.innerHTML = html;
    }
    
    formatNumber(num, decimals = 2) {
        return new Intl.NumberFormat('en-AU', {
            minimumFractionDigits: decimals,
            maximumFractionDigits: decimals
        }).format(num);
    }
}

// Auto-initialize converters when DOM loads
document.addEventListener('DOMContentLoaded', function() {
    const converters = document.querySelectorAll('.rba-currency-converter form');
    converters.forEach((form, index) => {
        new RBACurrencyConverter(`#${form.id || 'rba-converter-form-' + index}`);
    });
});

Frontend Styling

/* assets/frontend.css */

.rba-currency-converter {
    background: #fff;
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 20px;
    margin: 20px 0;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

.converter-header {
    text-align: center;
    margin-bottom: 20px;
    padding-bottom: 15px;
    border-bottom: 1px solid #eee;
}

.converter-header h3 {
    margin: 0 0 5px 0;
    color: #333;
    font-size: 24px;
}

.converter-subtitle {
    margin: 0;
    color: #666;
    font-size: 14px;
}

.converter-form {
    margin-bottom: 20px;
}

.form-row {
    margin-bottom: 20px;
}

.currency-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 15px;
    align-items: end;
}

.form-group {
    display: flex;
    flex-direction: column;
}

.form-group label {
    font-weight: 600;
    margin-bottom: 5px;
    color: #333;
}

.form-group input,
.form-group select {
    padding: 12px;
    border: 2px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
    transition: border-color 0.2s;
}

.form-group input:focus,
.form-group select:focus {
    outline: none;
    border-color: #0073aa;
}

.swap-currencies {
    background: #f7f7f7;
    border: 2px solid #ddd;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    font-size: 18px;
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.swap-currencies:hover {
    background: #0073aa;
    color: white;
    border-color: #0073aa;
}

.historical-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 15px;
    align-items: end;
    padding: 15px;
    background: #f9f9f9;
    border-radius: 4px;
}

.toggle-historical {
    background: #f7f7f7;
    border: 1px solid #ddd;
    padding: 8px 15px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
}

.convert-button {
    width: 100%;
    background: linear-gradient(135deg, #0073aa 0%, #005177 100%);
    color: white;
    border: none;
    padding: 15px;
    border-radius: 4px;
    font-size: 18px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.2s;
}

.convert-button:hover:not(:disabled) {
    transform: translateY(-1px);
}

.convert-button:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.conversion-result {
    background: #f0f8ff;
    border: 1px solid #b3d9ff;
    border-radius: 4px;
    padding: 20px;
    margin-bottom: 20px;
}

.result-amount {
    font-size: 24px;
    font-weight: 600;
    color: #0073aa;
    margin-bottom: 10px;
    text-align: center;
}

.result-details {
    font-size: 14px;
    color: #666;
    text-align: center;
}

.result-details div {
    margin-bottom: 5px;
}

.rates-grid {
    border-top: 1px solid #eee;
    padding-top: 20px;
}

.rates-grid h4 {
    text-align: center;
    margin-bottom: 15px;
    color: #333;
}

.rates-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
}

.rate-item {
    background: #f9f9f9;
    padding: 12px;
    border-radius: 4px;
    text-align: center;
    border: 1px solid #eee;
}

.currency-code {
    display: block;
    font-weight: 600;
    margin-bottom: 5px;
    color: #333;
}

.rate-value {
    display: block;
    color: #0073aa;
    font-size: 16px;
}

.converter-footer {
    text-align: center;
    margin-top: 20px;
    padding-top: 15px;
    border-top: 1px solid #eee;
}

.converter-footer small {
    color: #666;
    font-size: 12px;
}

.rba-currency-error {
    color: #d63638;
    font-weight: 500;
}

/* WooCommerce Integration */
.rba-currency-switcher {
    background: #f7f7f7;
    padding: 15px;
    margin-bottom: 20px;
    border-radius: 4px;
    text-align: center;
}

.rba-currency-switcher label {
    margin-right: 10px;
    font-weight: 500;
}

.rba-currency-switcher select {
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
}

.currency-notice {
    color: #666;
    font-size: 12px;
}

/* Responsive Design */
@media (max-width: 768px) {
    .currency-row {
        grid-template-columns: 1fr;
        gap: 15px;
    }
    
    .swap-currencies {
        order: 3;
        justify-self: center;
        margin: 10px 0;
    }
    
    .historical-row {
        grid-template-columns: 1fr;
        gap: 10px;
    }
    
    .rates-container {
        grid-template-columns: repeat(2, 1fr);
    }
    
    .result-amount {
        font-size: 20px;
    }
}

@media (max-width: 480px) {
    .rba-currency-converter {
        padding: 15px;
    }
    
    .rates-container {
        grid-template-columns: 1fr;
    }
}

Usage Examples

Basic Converter

[rba_currency_converter]

Customized Converter

[rba_currency_converter from="USD" to="AUD" amount="500" show_historical="true"]

Display Current Rate

Current USD rate: [rba_currency_rate from="AUD" to="USD" decimals="4"]

Convert Specific Amount

100 AUD = [rba_currency_convert from="AUD" to="USD" amount="100"]

WooCommerce Integration

Enable currency switcher and price conversion in WooCommerce → Settings → General.

Admin Panel Integration

<?php
// includes/class-admin.php

class RBA_Currency_Admin {
    
    public function __construct() {
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('admin_init', array($this, 'init_settings'));
    }
    
    public function add_admin_menu() {
        add_options_page(
            'RBA Currency Converter',
            'RBA Currency',
            'manage_options',
            'rba-currency',
            array($this, 'admin_page')
        );
    }
    
    public function admin_page() {
        ?>
        <div class="wrap">
            <h1><?php _e('RBA Currency Converter Settings', 'rba-currency'); ?></h1>
            
            <form method="post" action="options.php">
                <?php
                settings_fields('rba_currency_settings');
                do_settings_sections('rba_currency_settings');
                submit_button();
                ?>
            </form>
            
            <div class="rba-currency-test-section">
                <h2><?php _e('Test API Connection', 'rba-currency'); ?></h2>
                <button type="button" id="test-api" class="button"><?php _e('Test Connection', 'rba-currency'); ?></button>
                <div id="test-result"></div>
            </div>
        </div>
        
        <script>
        jQuery(document).ready(function($) {
            $('#test-api').on('click', function() {
                const button = $(this);
                const result = $('#test-result');
                
                button.prop('disabled', true).text('Testing...');
                
                $.post(ajaxurl, {
                    action: 'rba_test_api_connection',
                    nonce: '<?php echo wp_create_nonce('rba_test_api'); ?>'
                }, function(response) {
                    if (response.success) {
                        result.html('<div class="notice notice-success"><p>API connection successful!</p></div>');
                    } else {
                        result.html('<div class="notice notice-error"><p>Error: ' + response.data + '</p></div>');
                    }
                }).always(function() {
                    button.prop('disabled', false).text('Test Connection');
                });
            });
        });
        </script>
        <?php
    }
    
    public function init_settings() {
        register_setting('rba_currency_settings', 'rba_currency_api_key');
        register_setting('rba_currency_settings', 'rba_currency_default_from');
        register_setting('rba_currency_settings', 'rba_currency_default_to');
        register_setting('rba_currency_settings', 'rba_currency_cache_duration');
        register_setting('rba_currency_settings', 'rba_currency_decimal_places');
        
        add_settings_section(
            'rba_currency_api_section',
            __('API Settings', 'rba-currency'),
            null,
            'rba_currency_settings'
        );
        
        add_settings_field(
            'rba_currency_api_key',
            __('API Key', 'rba-currency'),
            array($this, 'api_key_field'),
            'rba_currency_settings',
            'rba_currency_api_section'
        );
        
        add_settings_section(
            'rba_currency_display_section',
            __('Display Settings', 'rba-currency'),
            null,
            'rba_currency_settings'
        );
        
        add_settings_field(
            'rba_currency_default_from',
            __('Default From Currency', 'rba-currency'),
            array($this, 'default_from_field'),
            'rba_currency_settings',
            'rba_currency_display_section'
        );
        
        add_settings_field(
            'rba_currency_default_to',
            __('Default To Currency', 'rba-currency'),
            array($this, 'default_to_field'),
            'rba_currency_settings',
            'rba_currency_display_section'
        );
        
        add_settings_field(
            'rba_currency_decimal_places',
            __('Decimal Places', 'rba-currency'),
            array($this, 'decimal_places_field'),
            'rba_currency_settings',
            'rba_currency_display_section'
        );
        
        add_settings_field(
            'rba_currency_cache_duration',
            __('Cache Duration (seconds)', 'rba-currency'),
            array($this, 'cache_duration_field'),
            'rba_currency_settings',
            'rba_currency_display_section'
        );
    }
    
    public function api_key_field() {
        $value = get_option('rba_currency_api_key', '');
        echo "<input type='password' name='rba_currency_api_key' value='" . esc_attr($value) . "' class='regular-text' />";
        echo "<p class='description'>Get your API key from <a href='https://app.exchangeratesapi.com.au' target='_blank'>app.exchangeratesapi.com.au</a></p>";
    }
    
    public function default_from_field() {
        $value = get_option('rba_currency_default_from', 'AUD');
        echo "<select name='rba_currency_default_from'>";
        $currencies = array('AUD', 'USD', 'EUR', 'GBP', 'JPY', 'CAD', 'CHF');
        foreach ($currencies as $currency) {
            $selected = selected($value, $currency, false);
            echo "<option value='$currency' $selected>$currency</option>";
        }
        echo "</select>";
    }
    
    public function default_to_field() {
        $value = get_option('rba_currency_default_to', 'USD');
        echo "<select name='rba_currency_default_to'>";
        $currencies = array('AUD', 'USD', 'EUR', 'GBP', 'JPY', 'CAD', 'CHF');
        foreach ($currencies as $currency) {
            $selected = selected($value, $currency, false);
            echo "<option value='$currency' $selected>$currency</option>";
        }
        echo "</select>";
    }
    
    public function decimal_places_field() {
        $value = get_option('rba_currency_decimal_places', 2);
        echo "<input type='number' name='rba_currency_decimal_places' value='" . esc_attr($value) . "' min='0' max='8' />";
    }
    
    public function cache_duration_field() {
        $value = get_option('rba_currency_cache_duration', 300);
        echo "<input type='number' name='rba_currency_cache_duration' value='" . esc_attr($value) . "' min='60' max='3600' />";
        echo "<p class='description'>How long to cache exchange rate data (60-3600 seconds)</p>";
    }
}

Why WordPress + RBA API?

This combination provides:

  1. Easy Integration: Shortcodes work anywhere in WordPress
  2. WooCommerce Ready: Multi-currency pricing for international customers
  3. Official Data: RBA rates ensure accuracy for Australian tax compliance
  4. Performance Optimized: Caching and database storage minimize API calls
  5. User Friendly: Admin panel for non-technical users

Perfect for Australian businesses with WordPress sites who need professional currency conversion features without complex development.

For backend API integrations and automation, explore our Python tutorial with database caching and scheduled updates. Frontend developers should check our React implementation for modern single-page applications.

The official RBA data ensures compliance with Australian financial regulations and ATO requirements.


We are not affiliated with or endorsed by the Reserve Bank of Australia.

For API documentation, visit Exchange Rates API Docs