Skip to content

DucMinhNe/URL-Shorten

Repository files navigation

URL Shortener with Ads

A pay-per-view URL shortener — guests and members shorten links, each visit passes through a 5-second interstitial ad page with human verification, and link owners earn a configurable CPM on every valid view. Built on Laravel 12 with a Blade + Tailwind storefront and a full Filament 3 admin panel.

PHP Laravel Filament MySQL Tailwind CSS Cloudflare Turnstile

Overview

This is an adf.ly-style link monetization platform. A user shortens a long URL; anyone who opens the short link lands on an interstitial page that shows ad slots and a 5-second countdown gated by a captcha. When the visit clears verification — captcha passed, not a duplicate from the same IP within the dedup window, and not the owner clicking their own link — the link owner is credited at the configured per-1000-views rate. Earnings accumulate in a wallet that users can cash out through MoMo, ZaloPay, or PayPal, with payouts approved manually by an admin.

The public-facing app (shorten form, dashboard, interstitial, payouts, referrals, leaderboard) is built with plain Blade controllers and views; all back-office administration runs on a separate Filament 3 panel at /admin.

Features

Link shortening

  • Shorten URLs with a random slug or a custom alias, optional password protection, and a guest mode (anonymous shorten from the landing page, rate-limited to 10/min)
  • Bulk create, clone, CSV export, per-link stats, and QR code generation (endroid/qr-code)
  • Public REST APIPOST /api/v1/shorten authenticated with per-user API tokens that members manage from their dashboard

Interstitial & monetization

  • 5-second interstitial ad page with ad slots served from admin-managed ad campaigns (impressions and clicks are tracked)
  • Human verification via Cloudflare Turnstile, with a graceful fallback to a custom "I'm not a robot" checkbox when no Turnstile keys are configured (demo/dev mode)
  • IP deduplication over a configurable window (ip_dedup_hours, default 24h) and anti-self-click protection so owners can't farm their own links
  • Configurable CPM earnings — owners are credited rate_per_1000_views / 1000 per valid view (default rate 5000, editable in admin settings)
  • Referral commissions — a configurable percentage (referral_rate_percent, default 10%) of a referred user's earnings is credited to the referrer

Accounts & payouts

  • Wallet with transaction ledger; payout requests via MoMo, ZaloPay, or PayPal, with balance held on request and refunded on rejection
  • User dashboard with KPI cards and click/earnings charts
  • Premium upgrade, promo codes, and a public leaderboard of top earners
  • Authentication via email/password (Laravel Breeze) and Google OAuth (Laravel Socialite)
  • Multi-language UI (Vietnamese + English) with a cookie-based locale switcher

Admin panel (Filament 3, at /admin)

  • CRUD resources for users, roles, short links, ad campaigns, payout requests, settings, blacklisted domains, tags, promo codes, announcements, FAQs & FAQ categories, email templates, captcha questions, support tickets, reported links, and audit logs (19 Filament resources)
  • Dashboard widgets: stats overview, revenue trend, ad performance, user growth, clicks chart, pending payouts, and a top-earners table
  • Payout moderation (mark paid with a transaction reference, or reject with a note that refunds the held balance)

Tech stack

Layer Technology
Language PHP 8.2+
Framework Laravel 12
Admin panel Filament 3
Database MySQL 8 (MariaDB 10.6+ also works)
Frontend Blade, Tailwind CSS, Alpine.js, Vite
Auth Laravel Breeze (email/password) + Laravel Socialite (Google OAuth)
Human verification Cloudflare Turnstile (with checkbox fallback)
Extras endroid/qr-code (QR codes), blade-ui-kit/blade-heroicons (icons)
Testing Pest 4

Getting started

Requirements

  • PHP 8.2+ and Composer 2.x
  • Node.js 20+
  • MySQL 8 (or MariaDB 10.6+)

Installation

git clone https://github.com/DucMinhNe/URL-Shorten.git
cd URL-Shorten

composer install
npm install

cp .env.example .env
php artisan key:generate

# Create the database, then set DB_* in .env
mysql -u root -e "CREATE DATABASE url_shorten CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# Run migrations and seed demo data
php artisan migrate --seed

# Build front-end assets
npm run build

# Serve
php artisan serve

The app is served at http://localhost:8000; the admin panel lives at http://localhost:8000/admin.

For background work (wallet credits, scheduled tasks) run the queue worker and scheduler:

php artisan queue:work
php artisan schedule:run   # or a cron entry: * * * * * php artisan schedule:run

Optional configuration

Google OAuth — create an OAuth client in the Google Cloud Console with redirect URI http://localhost:8000/auth/google/callback, then set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env.

Cloudflare Turnstile — the app accepts the checkbox fallback when unconfigured. To enable real verification, register at Cloudflare Turnstile and set TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY in .env.

Project structure

app/
├── Filament/
│   ├── Resources/             # 19 admin CRUD resources
│   └── Widgets/               # 7 dashboard widgets
├── Http/Controllers/          # Blade frontend: Home, ShortLink, Redirect,
│   │                          #   Interstitial, Dashboard, Payout, Referral,
│   │                          #   Premium, Leaderboard, ApiToken, Profile, Locale
│   └── Api/ShortenController   # public REST shorten endpoint
├── Models/                    # Eloquent models (ShortLink, Click, AdCampaign,
│   │                          #   PayoutRequest, WalletTransaction, IpViewLog, …)
├── Services/                  # Business logic: ShortLinkService, ClickTrackingService,
│   │                          #   CaptchaService, AdServingService, WalletService,
│   │                          #   PayoutService, SettingService
└── Providers/Filament/        # AdminPanelProvider (panel registration)

routes/
├── web.php                    # storefront + interstitial routes
├── api.php                    # POST /api/v1/shorten
└── auth.php                   # Breeze auth routes

resources/views/               # Blade views (home, dashboard, links, payout,
                               #   interstitial, referral, premium, leaderboard, legal)
database/
├── migrations/                # schema
├── factories/
└── seeders/                   # demo data

Request flow

  1. Shorten — a guest posts to /shorten (or a member uses /links), the server generates a slug or uses the custom alias and stores the link.
  2. VisitGET /{slug} resolves the link (prompting for a password if protected), then renders the interstitial with ad slots, a 5-second countdown, and the captcha.
  3. Verify — after the countdown and captcha, POST /{slug}/verify validates the captcha, applies IP dedup and anti-self-click checks, credits the owner on a valid view, and returns the destination URL for the client-side redirect.
  4. Cash out — a user submits a payout request from /payout; an admin approves or rejects it from the Filament panel.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors