HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Http/Controllers/Refactor/FunnelReportController.php
<?php

namespace App\Http\Controllers\Refactor;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Model\Funnel;
use App\Model\FunnelPageView;
use App\Model\FunnelConversion;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class FunnelReportController extends Controller
{
    public function show(Request $request, $uid)
    {
        $funnel = Funnel::ofCustomer($request->user()->customer)
            ->notTemplate()
            ->where('uid', $uid)->first();

        if (!$funnel) {
            return $this->notAuthorized();
        }

        // Date range
        $from = $request->from ? Carbon::parse($request->from)->startOfDay() : now()->subDays(30)->startOfDay();
        $to = $request->to ? Carbon::parse($request->to)->endOfDay() : now()->endOfDay();

        $customerId = $request->user()->customer->id;

        // Overall stats
        $totalViews = FunnelPageView::ofFunnel($funnel)->dateRange($from, $to)->count();
        $uniqueVisitors = FunnelPageView::ofFunnel($funnel)->dateRange($from, $to)->distinct('session_id')->count('session_id');
        $totalConversions = FunnelConversion::ofFunnel($funnel)->dateRange($from, $to)->count();
        $totalRevenue = FunnelConversion::ofFunnel($funnel)->ofType('purchase')->dateRange($from, $to)->sum('value');
        $optins = FunnelConversion::ofFunnel($funnel)->ofType('optin')->dateRange($from, $to)->count();
        $purchases = FunnelConversion::ofFunnel($funnel)->ofType('purchase')->dateRange($from, $to)->count();
        $conversionRate = $uniqueVisitors > 0 ? round(($totalConversions / $uniqueVisitors) * 100, 1) : 0;

        // Per-step stats
        $steps = $funnel->steps()->ordered()->get();
        $stepStats = [];

        foreach ($steps as $step) {
            $views = FunnelPageView::where('funnel_step_id', $step->id)->dateRange($from, $to)->count();
            $uniqueStepVisitors = FunnelPageView::where('funnel_step_id', $step->id)->dateRange($from, $to)->distinct('session_id')->count('session_id');
            $stepConversions = FunnelConversion::where('funnel_step_id', $step->id)->dateRange($from, $to)->count();
            $stepRevenue = FunnelConversion::where('funnel_step_id', $step->id)->ofType('purchase')->dateRange($from, $to)->sum('value');

            $stepStats[] = [
                'step'        => $step,
                'views'       => $views,
                'visitors'    => $uniqueStepVisitors,
                'conversions' => $stepConversions,
                'revenue'     => $stepRevenue,
                'rate'        => $uniqueStepVisitors > 0 ? round(($stepConversions / $uniqueStepVisitors) * 100, 1) : 0,
            ];
        }

        // Daily views for chart (last 30 days or selected range)
        $dailyViews = FunnelPageView::ofFunnel($funnel)
            ->dateRange($from, $to)
            ->select(DB::raw('DATE(viewed_at) as date'), DB::raw('COUNT(*) as count'))
            ->groupBy('date')
            ->orderBy('date')
            ->pluck('count', 'date')
            ->toArray();

        $dailyConversions = FunnelConversion::ofFunnel($funnel)
            ->dateRange($from, $to)
            ->select(DB::raw('DATE(converted_at) as date'), DB::raw('COUNT(*) as count'))
            ->groupBy('date')
            ->orderBy('date')
            ->pluck('count', 'date')
            ->toArray();

        // Build full date range for chart
        $chartDates = [];
        $chartViews = [];
        $chartConversions = [];
        $period = new \DatePeriod($from->copy(), new \DateInterval('P1D'), $to->copy()->addDay());
        foreach ($period as $date) {
            $key = $date->format('Y-m-d');
            $chartDates[] = $date->format('M j');
            $chartViews[] = $dailyViews[$key] ?? 0;
            $chartConversions[] = $dailyConversions[$key] ?? 0;
        }

        // Top referrers
        $topReferrers = FunnelPageView::ofFunnel($funnel)
            ->dateRange($from, $to)
            ->whereNotNull('referrer')
            ->where('referrer', '!=', '')
            ->select('referrer', DB::raw('COUNT(*) as count'))
            ->groupBy('referrer')
            ->orderByDesc('count')
            ->limit(5)
            ->pluck('count', 'referrer')
            ->toArray();

        // Device breakdown
        $devices = FunnelPageView::ofFunnel($funnel)
            ->dateRange($from, $to)
            ->select('device_type', DB::raw('COUNT(*) as count'))
            ->groupBy('device_type')
            ->pluck('count', 'device_type')
            ->toArray();

        return view('refactor.pages.funnels.report', [
            'funnel'           => $funnel,
            'from'             => $from,
            'to'               => $to,
            'totalViews'       => $totalViews,
            'uniqueVisitors'   => $uniqueVisitors,
            'totalConversions' => $totalConversions,
            'totalRevenue'     => $totalRevenue,
            'optins'           => $optins,
            'purchases'        => $purchases,
            'conversionRate'   => $conversionRate,
            'stepStats'        => $stepStats,
            'chartDates'       => $chartDates,
            'chartViews'       => $chartViews,
            'chartConversions' => $chartConversions,
            'topReferrers'     => $topReferrers,
            'devices'          => $devices,
        ]);
    }

    /**
     * Page views detail page (list all views with filters).
     */
    public function pageViews(Request $request, $uid)
    {
        $funnel = Funnel::ofCustomer($request->user()->customer)
            ->notTemplate()
            ->where('uid', $uid)->first();

        if (!$funnel) {
            return $this->notAuthorized();
        }

        $steps = $funnel->steps()->ordered()->get();

        return view('refactor.pages.funnels.page_views', [
            'funnel' => $funnel,
            'steps'  => $steps,
        ]);
    }

    /**
     * AJAX listing for page views.
     */
    public function pageViewsListing(Request $request, $uid)
    {
        $funnel = Funnel::ofCustomer($request->user()->customer)
            ->notTemplate()
            ->where('uid', $uid)->first();

        if (!$funnel) {
            return $this->notAuthorized();
        }

        $query = FunnelPageView::where('funnel_page_views.funnel_id', $funnel->id)
            ->leftJoin('funnel_steps', 'funnel_page_views.funnel_step_id', '=', 'funnel_steps.id')
            ->select('funnel_page_views.*', 'funnel_steps.name as step_name', 'funnel_steps.type as step_type');

        // Date range
        if ($request->from) {
            $query->where('funnel_page_views.viewed_at', '>=', Carbon::parse($request->from)->startOfDay());
        }
        if ($request->to) {
            $query->where('funnel_page_views.viewed_at', '<=', Carbon::parse($request->to)->endOfDay());
        }

        // Filter by step
        if ($request->step_id) {
            $query->where('funnel_page_views.funnel_step_id', $request->step_id);
        }

        // Filter by device
        if ($request->device) {
            $query->where('funnel_page_views.device_type', $request->device);
        }

        // Filter: unique visitors only
        if ($request->unique == '1') {
            $query->whereIn('funnel_page_views.id', function ($sub) use ($funnel, $request) {
                $sub->selectRaw('MIN(funnel_page_views.id)')
                    ->from('funnel_page_views')
                    ->where('funnel_page_views.funnel_id', $funnel->id);
                if ($request->from) {
                    $sub->where('funnel_page_views.viewed_at', '>=', Carbon::parse($request->from)->startOfDay());
                }
                if ($request->to) {
                    $sub->where('funnel_page_views.viewed_at', '<=', Carbon::parse($request->to)->endOfDay());
                }
                $sub->groupBy('funnel_page_views.session_id');
            });
        }

        // Search (IP, referrer, user agent, session_id)
        if ($keyword = $request->keyword) {
            $query->where(function ($q) use ($keyword) {
                $q->where('funnel_page_views.ip_address', 'like', "%{$keyword}%")
                  ->orWhere('funnel_page_views.referrer', 'like', "%{$keyword}%")
                  ->orWhere('funnel_page_views.user_agent', 'like', "%{$keyword}%")
                  ->orWhere('funnel_page_views.session_id', 'like', "%{$keyword}%")
                  ->orWhere('funnel_steps.name', 'like', "%{$keyword}%");
            });
        }

        // Sort
        $sortBy = $request->sort_by ?: 'viewed_at';
        $sortDir = $request->sort_direction ?: 'desc';
        $allowed = ['viewed_at', 'ip_address', 'device_type', 'referrer', 'step_name'];
        if (in_array($sortBy, $allowed)) {
            $query->orderBy($sortBy === 'step_name' ? 'funnel_steps.name' : "funnel_page_views.{$sortBy}", $sortDir);
        } else {
            $query->orderByDesc('funnel_page_views.viewed_at');
        }

        $views = $query->paginate($request->per_page ?: 25);

        return view('refactor.pages.funnels._page_views_list', [
            'views'  => $views,
            'funnel' => $funnel,
        ]);
    }
}