logo
image
Jun 10, 2026 - 07:54 PM

Laravel WhatsApp Widget: Blade Snippet and API Upgrade Angle

Laravel WhatsApp integration in three layers: a Blade partial that reads the phone from config/wutt.php, a Vite-bundled JS widget for SPA-style behavior, and a small Wutt API example to fetch a dynamic phone number per page. Target link: wa.me/966500000000.

1. Blade partial with config-driven phone

Create the config file first:

<?php // config/wutt.php
return [
    'phone'   => env('WUTT_PHONE', '966500000000'),
    'message' => env('WUTT_MESSAGE', "Hi, I'd like to know more about Wutt."),
    'api_key' => env('WUTT_API_KEY'),
    'api_url' => env('WUTT_API_URL', 'https://api.wutt.net/v1'),
];

Then the Blade partial at resources/views/partials/wutt-button.blade.php:

@php
    $phone = preg_replace('/[^0-9]/', '', config('wutt.phone', '966500000000'));
    $msg   = config('wutt.message', "Hi, I'd like to know more about Wutt.");
    $href  = "https://wa.me/{$phone}?text=" . rawurlencode($msg);
    $label = $label ?? 'Chat with us';
@endphp
<a href="{{ $href }}" target="_blank" rel="noopener"
   class="wutt-wa-btn {{ $class ?? '' }}"
   data-wutt-phone="{{ $phone }}" aria-label="Chat on WhatsApp">
  <svg viewBox="0 0 32 32" width="20" height="20" aria-hidden="true">
    <path fill="currentColor" d="M16 3C9 3 3.5 8.5 3.5 15.5c0 2.4.7 4.7 1.9 6.7L3 29l7-1.8c1.9 1 4 1.5 6 1.5 7 0 12.5-5.5 12.5-12.5S23 3 16 3z"/>
  </svg>
  <span>{{ $label }}</span>
</a>
@once
  @push('styles')
    <style>
      .wutt-wa-btn{position:fixed;right:20px;bottom:20px;z-index:9999;
        display:inline-flex;align-items:center;gap:10px;background:#25D366;
        color:#fff;padding:12px 18px;border-radius:999px;text-decoration:none;
        font-weight:700;box-shadow:0 10px 30px rgba(0,0,0,.25)}
    </style>
  @endpush
@endonce

Include it in your main layout, after the page content:

{{-- resources/views/layouts/app.blade.php --}}
</main>
@include('partials.wutt-button')
@stack('scripts')

You can override the label per page:

@include('partials.wutt-button', ['label' => 'Book a free consult'])

2. Vite + JS bundling for the JS widget

Create resources/js/wutt-widget.js:

export function initWuttWidget({ phone, message, target = document.body }) {
    const digits = String(phone || "966500000000").replace(/\D/g, "");
    const text   = encodeURIComponent(message || "Hi, I'd like to know more about Wutt.");
    const href   = `https://wa.me/${digits}?text=${text}`;

    const a = document.createElement("a");
    a.href = href; a.target = "_blank"; a.rel = "noopener";
    a.setAttribute("aria-label", "Chat on WhatsApp");
    a.className = "wutt-wa-js";
    a.innerHTML = `
      <svg viewBox="0 0 32 32" width="22" height="22" aria-hidden="true">
        <path fill="#fff" d="M16 3C9 3 3.5 8.5 3.5 15.5c0 2.4.7 4.7 1.9 6.7L3 29l7-1.8c1.9 1 4 1.5 6 1.5 7 0 12.5-5.5 12.5-12.5S23 3 16 3z"/>
      </svg>
      <span>Chat</span>`;

    const style = document.createElement("style");
    style.textContent = `
      .wutt-wa-js{position:fixed;right:20px;bottom:20px;z-index:9999;
        display:inline-flex;align-items:center;gap:10px;background:#25D366;
        color:#fff;padding:12px 18px;border-radius:999px;text-decoration:none;
        font-weight:700;box-shadow:0 10px 30px rgba(0,0,0,.25)}`;

    document.head.appendChild(style);
    target.appendChild(a);
    return a;
}

Register it in your app.js or resources/js/app.js:

import { initWuttWidget } from "./wutt-widget.js";
document.addEventListener("DOMContentLoaded", () => {
    initWuttWidget({
        phone:   window.WUTT_PHONE   || "966500000000",
        message: window.WUTT_MESSAGE || "Hi, I'd like to know more about Wutt.",
    });
});

Build it:

npm run build   # uses Vite

Add to your Blade layout:

@vite(['resources/js/app.js'])

3. Wutt API integration for dynamic phone numbers

If the phone number should come from Wutt (for example, per workspace, per agent, or per working-hours schedule), call the Wutt API from a controller or a service. Use a tiny service class:

<?php // app/Services/WuttClient.php
namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class WuttClient
{
    public function phone(?string $workspace = null): string
    {
        $key = config('wutt.api_key');
        $url = rtrim(config('wutt.api_url'), '/');

        return Cache::remember("wutt.phone." . ($workspace ?: 'default'), 300, function () use ($key, $url, $workspace) {
            $resp = Http::withToken($key)
                ->acceptJson()
                ->get("{$url}/workspaces/" . ($workspace ?: 'default') . "/whatsapp");

            if ($resp->successful() && ($resp->json('phone'))) {
                return preg_replace('/[^0-9]/', '', $resp->json('phone'));
            }
            return preg_replace('/[^0-9]/', '', config('wutt.phone', '966500000000'));
        });
    }

    public function sendTemplate(string $to, string $template, array $params = []): array
    {
        $url = rtrim(config('wutt.api_url'), '/');
        return Http::withToken(config('wutt.api_key'))
            ->post("{$url}/messages/template", [
                'to'       => $to,
                'template' => $template,
                'params'   => $params,
            ])->json();
    }
}

Bind it in AppServiceProvider:

$this->app->singleton(WuttClient::class);

Inject it in a controller and pass the phone to the partial:

// app/Http/Controllers/PageController.php
use App\Services\WuttClient;

public function show(Page $page, WuttClient $wutt)
{
    return view('pages.show', [
        'page'        => $page,
        'wutt_phone'  => $wutt->phone($page->workspace_slug),
    ]);
}
{{-- resources/views/pages/show.blade.php --}}
@include('partials.wutt-button', ['label' => 'Ask about this page'])

For automated template sends (cart recovery, booking reminders), call $wutt->sendTemplate($contactPhone, 'cart_recovery_v1', [$cartUrl, $total]) from a queued job.

Upgrade path

Start with the Blade partial (no build, no JS). When you need dynamic phones, drop in the WuttClient service. When you need richer UI (chat preview, agent photos, hours), bundle the JS widget via Vite. All three layers live in the same code base and can be turned on one at a time.

Add Wutt to your site — start $1 trial

Drop the widget in, then keep every reply, click, lead, and order inside Wutt Inbox, Wutt Book, Wutt Reviews, Wutt Loyalty, and the CRM follow-up workspace.

Start $1 trial