← back to Wine Finder Next

app/api/affiliate/track/route.ts

123 lines

import { NextRequest, NextResponse } from 'next/server';

const googleSheets = require('@/lib/services/googleSheets');

// In-memory storage for development (replace with database in production)
const clicksStorage: any[] = [];

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();

    // Get client IP and user agent
    const ip = request.headers.get('x-forwarded-for') ||
               request.headers.get('x-real-ip') ||
               'unknown';
    const userAgent = request.headers.get('user-agent') || 'unknown';

    if (body.bulk) {
      // Bulk tracking
      const clicks = body.clicks.map((click: any) => ({
        ...click,
        ipAddress: ip,
        userAgent: userAgent
      }));

      clicksStorage.push(...clicks);

      // Log to Google Sheets asynchronously
      googleSheets.logAffiliateClicks(clicks).catch((err: Error) => {
        console.error('Failed to log bulk clicks to sheets:', err.message);
      });

      return NextResponse.json({
        success: true,
        tracked: clicks.length
      });
    } else {
      // Single click tracking
      const click = {
        ...body,
        ipAddress: ip,
        userAgent: userAgent
      };

      clicksStorage.push(click);

      // Log to Google Sheets asynchronously
      googleSheets.logAffiliateClick(click).catch((err: Error) => {
        console.error('Failed to log click to sheets:', err.message);
      });

      return NextResponse.json({
        success: true,
        clickId: clicksStorage.length
      });
    }
  } catch (error: any) {
    console.error('Error tracking affiliate click:', error);
    return NextResponse.json(
      { error: 'Failed to track click', message: error.message },
      { status: 500 }
    );
  }
}

export async function GET(request: NextRequest) {
  try {
    const searchParams = request.nextUrl.searchParams;
    const partnerId = searchParams.get('partnerId');
    const startDate = searchParams.get('startDate');
    const endDate = searchParams.get('endDate');

    let filteredClicks = clicksStorage;

    // Filter by partner
    if (partnerId) {
      filteredClicks = filteredClicks.filter(c => c.partnerId === partnerId);
    }

    // Filter by date range
    if (startDate) {
      filteredClicks = filteredClicks.filter(c => c.timestamp >= startDate);
    }
    if (endDate) {
      filteredClicks = filteredClicks.filter(c => c.timestamp <= endDate);
    }

    // Calculate stats
    const now = new Date();
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
    const monthAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000);

    const stats = {
      total: filteredClicks.length,
      today: filteredClicks.filter(c => new Date(c.timestamp) >= today).length,
      thisWeek: filteredClicks.filter(c => new Date(c.timestamp) >= weekAgo).length,
      thisMonth: filteredClicks.filter(c => new Date(c.timestamp) >= monthAgo).length,
      byPartner: {} as Record<string, number>
    };

    // Group by partner
    filteredClicks.forEach(click => {
      if (!stats.byPartner[click.partnerId]) {
        stats.byPartner[click.partnerId] = 0;
      }
      stats.byPartner[click.partnerId]++;
    });

    return NextResponse.json({
      success: true,
      stats,
      clicks: filteredClicks.slice(-100) // Last 100 clicks
    });
  } catch (error: any) {
    console.error('Error getting affiliate stats:', error);
    return NextResponse.json(
      { error: 'Failed to get stats', message: error.message },
      { status: 500 }
    );
  }
}