Integrationsbeispiele

Vollständige Widget-Implementierungen für verschiedene Anwendungsfälle.

Grundlegende Implementierung

Das einfachste Beispiel: ein Inline-Widget auf Ihrer Buchungsseite.

HTML
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Termin buchen | Mi Salon</title>
    <style>
        body {
            font-family: system-ui, sans-serif;
            max-width: 600px;
            margin: 40px auto;
            padding: 0 20px;
        }
        h1 {
            text-align: center;
            margin-bottom: 30px;
        }
    </style>
</head>
<body>

    <h1>Buchen Sie Ihren Termin</h1>

    <div id="salonbookit-widget"></div>

    <script src="https://app.salonbookit.com/static/widget/v1/salonbookit-widget.min.js"></script>
    <script>
        SalonBookIt.init({
            apiKey: 'IHR_API_SCHLUESSEL',
            container: '#salonbookit-widget',
            theme: 'light',
            locale: 'es'
        });
    </script>

</body>
</html>

Button, der Modal öffnet

Ein schwebender Button, der das Widget in einem Popup öffnet. Ideal für Landing Pages.

HTML

Vorausgewählter Service

Nützlich für einzelne Serviceseiten, wo das Widget bereits einen Service ausgewählt haben soll.

HTML
<!-- Seite: /servicios/corte-clasico -->

<div class="service-page">
    <h1>Klassischer Schnitt</h1>
    <p>Unser beliebtester Haarschnitt für Herren.</p>
    <p><strong>Preis: 25€</strong> | <strong>Dauer: 30 min</strong></p>

    <h2>Diesen Service buchen</h2>
    <div id="widget"></div>
</div>

<script src="https://app.salonbookit.com/static/widget/v1/salonbookit-widget.min.js"></script>
<script>
    // Die Service-ID erhalten Sie von Ihrem Backend oder der URL
    const serviceId = 15; // ID del "Klassischer Schnitt"

    SalonBookIt.init({
        apiKey: 'IHR_API_SCHLUESSEL',
        container: '#widget',
        serviceId: serviceId, // Wählt diesen Service vor
        allowMultipleServices: false // Erlaubt nur diesen Service
    });
</script>

Google Analytics-Integration

Verfolgen Sie jeden Schritt des Buchungstrichters.

JavaScript
SalonBookIt.init({
    apiKey: 'IHR_API_SCHLUESSEL',
    container: '#widget',

    onReady: (business) => {
        gtag('event', 'widget_loaded', {
            'business_name': business.nombre
        });
    },

    onStepChange: (step, data) => {
        gtag('event', 'booking_step', {
            'step_name': step,
            'services_count': data.services?.length || 0
        });
    },

    onServiceSelect: (service, selected, allSelected) => {
        if (selected) {
            gtag('event', 'add_to_cart', {
                'items': [{
                    'id': service.id,
                    'name': service.nombre,
                    'price': service.precio
                }]
            });
        }
    },

    onBookingComplete: (booking) => {
        gtag('event', 'purchase', {
            'transaction_id': booking.id,
            'value': booking.total,
            'currency': 'EUR',
            'items': booking.servicios.map(s => ({
                'id': s.id,
                'name': s.nombre,
                'price': s.precio
            }))
        });

        // Facebook Pixel
        fbq('track', 'Purchase', {
            value: booking.total,
            currency: 'EUR'
        });
    },

    onPaymentComplete: (payment) => {
        gtag('event', 'payment_complete', {
            'payment_method': 'stripe',
            'amount': payment.amount
        });
    },

    onError: (error) => {
        gtag('event', 'exception', {
            'description': error.message,
            'fatal': false
        });
    }
});

Benutzerdefinierte Stile

Passen Sie das Erscheinungsbild des Widgets vollständig an Ihre Marke an.

HTML + CSS
<style>
/* Benutzerdefiniertes Theme */
#mi-widget .sbk-widget {
    /* Markenfarben */
    --sbk-primary: #ff6b6b;
    --sbk-primary-hover: #ee5a5a;
    --sbk-background: #fafafa;
    --sbk-surface: #ffffff;
    --sbk-text: #2d3436;
    --sbk-text-secondary: #636e72;
    --sbk-border: #dfe6e9;

    /* Stärker abgerundete Ränder */
    --sbk-radius-sm: 8px;
    --sbk-radius-md: 12px;
    --sbk-radius-lg: 20px;

    /* Benutzerdefinierte Schrift */
    --sbk-font-family: 'Poppins', sans-serif;

    /* Stärkere Schatten */
    --sbk-shadow-md: 0 10px 40px rgba(0,0,0,0.15);
}

/* Hauptbutton-Stil */
#mi-widget .sbk-btn-primary {
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Service-Karten */
#mi-widget .sbk-service-card {
    border: 2px solid transparent;
    transition: all 0.3s ease;
}

#mi-widget .sbk-service-card:hover {
    border-color: var(--sbk-primary);
    transform: translateY(-2px);
}

#mi-widget .sbk-service-card.selected {
    border-color: var(--sbk-primary);
    background: rgba(255, 107, 107, 0.05);
}
</style>

<div id="mi-widget"></div>

<script src="https://app.salonbookit.com/static/widget/v1/salonbookit-widget.min.js"></script>
<script>
    SalonBookIt.init({
        apiKey: 'IHR_API_SCHLUESSEL',
        container: '#mi-widget',
        primaryColor: '#ff6b6b',
        borderRadius: '20px',
        fontFamily: 'Poppins, sans-serif'
    });
</script>

Vollständige React-Komponente

React (TypeScript)
import React, { useEffect, useRef, useState } from 'react';

interface BookingWidgetProps {
    apiKey: string;
    serviceId?: number;
    staffId?: number;
    onBookingComplete?: (booking: any) => void;
    onError?: (error: any) => void;
}

declare global {
    interface Window {
        SalonBookIt: any;
    }
}

const BookingWidget: React.FC<BookingWidgetProps> = ({
    apiKey,
    serviceId,
    staffId,
    onBookingComplete,
    onError
}) => {
    const containerRef = useRef<HTMLDivElement>(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    useEffect(() => {
        const loadScript = () => {
            return new Promise<void>((resolve, reject) => {
                if (window.SalonBookIt) {
                    resolve();
                    return;
                }

                const script = document.createElement('script');
                script.src = 'https://app.salonbookit.com/static/widget/v1/salonbookit-widget.min.js';
                script.async = true;
                script.onload = () => resolve();
                script.onerror = () => reject(new Error('Fehler beim Laden des Widgets'));
                document.body.appendChild(script);
            });
        };

        const initWidget = async () => {
            try {
                await loadScript();

                if (!containerRef.current) return;

                window.SalonBookIt.init({
                    apiKey,
                    container: containerRef.current,
                    serviceId,
                    staffId,
                    locale: 'es',
                    onReady: () => setLoading(false),
                    onBookingComplete: (booking: any) => {
                        onBookingComplete?.(booking);
                    },
                    onError: (err: any) => {
                        setError(err.message);
                        onError?.(err);
                    }
                });
            } catch (err) {
                setError('Fehler beim Laden des Widgets');
            }
        };

        initWidget();

        return () => {
            // Cleanup falls erforderlich
        };
    }, [apiKey, serviceId, staffId]);

    if (error) {
        return (
            <div className="widget-error">
                <p>Error: {error}</p>
                <button onClick={() => window.location.reload()}>
                    Erneut versuchen
                </button>
            </div>
        );
    }

    return (
        <div className="widget-wrapper">
            {loading && (
                <div className="widget-loading">
                    <div className="spinner" />
                    <p>Wird geladen...</p>
                </div>
            )}
            <div ref={containerRef} style={{ opacity: loading ? 0 : 1 }} />
        </div>
    );
};

export default BookingWidget;

// Verwendung:
// <BookingWidget
//     apiKey="hh_pub_live_..."
//     serviceId={15}
//     onBookingComplete={(booking) => navigate(`/confirmacion/${booking.id}`)}
// />

WordPress mit Shortcode

Erstellen Sie einen Shortcode, um das Widget einfach in Beiträgen und Seiten einzufügen.

PHP (functions.php)
<?php
/**
 * Shortcode für SalonBookIt-Widget
 * Verwendung: [salonbookit_widget service="15" staff="3"]
 */
function salonbookit_widget_shortcode($atts) {
    $atts = shortcode_atts([
        'service' => '',
        'staff' => '',
        'mode' => 'inline',
        'button_text' => 'Termin buchen'
    ], $atts);

    // Eindeutige ID für Container generieren
    $container_id = 'sbk-widget-' . uniqid();

    // JS-Optionen erstellen
    $options = [
        'apiKey' => get_option('salonbookit_api_key'),
        'container' => '#' . $container_id,
        'mode' => esc_attr($atts['mode']),
        'buttonText' => esc_attr($atts['button_text']),
        'locale' => substr(get_locale(), 0, 2)
    ];

    if (!empty($atts['service'])) {
        $options['serviceId'] = intval($atts['service']);
    }
    if (!empty($atts['staff'])) {
        $options['staffId'] = intval($atts['staff']);
    }

    $options_json = json_encode($options);

    ob_start();
    ?>
    <div id="<?php echo esc_attr($container_id); ?>"></div>
    <script>
    document.addEventListener('DOMContentLoaded', function() {
        if (window.SalonBookIt) {
            SalonBookIt.init(<?php echo $options_json; ?>);
        }
    });
    </script>
    <?php
    return ob_get_clean();
}
add_shortcode('salonbookit_widget', 'salonbookit_widget_shortcode');

// Script einreihen
function salonbookit_enqueue_scripts() {
    wp_enqueue_script(
        'salonbookit-widget',
        'https://app.salonbookit.com/static/widget/v1/salonbookit-widget.min.js',
        [],
        '1.0',
        true
    );
}
add_action('wp_enqueue_scripts', 'salonbookit_enqueue_scripts');

Verwendung im WordPress-Editor:

Shortcode
[salonbookit_widget]

[salonbookit_widget service="15"]

[salonbookit_widget mode="button" button_text="Termin anfragen"]