ProposalTrack

Self-hosted proposal sharing & tracking platform — Documentation

Version 1.0.0

Introduction

Welcome to ProposalTrack — thank you for your purchase!

ProposalTrack is a modern, self-hosted web application for sharing business proposals, quotes, and documents with clients and tracking exactly how they're viewed in real time. Upload a PDF or Word document, generate a private share link, and instantly see when it was opened, how long it was read, where the visitor is located, and what device and browser they used.

Built on Laravel 11 and PHP 8.2+, the script is lightweight, easy to install on any standard LAMP/LEMP stack (including cPanel shared hosting), and ships with a powerful admin dashboard, complete email workflow, and a clean responsive front-end.

Quick Start Most users can complete installation in under 5 minutes using the built-in Web Installer. Just upload the files, point your browser at the domain, and follow the wizard.

Features Overview

Everything you need to share, track, and manage proposals — in one self-hosted package.

Core Features

Drag-and-Drop Upload

Upload PDF, DOC, or DOCX files with a simple, mobile-friendly form. No account needed.

Private Share Links

Each proposal gets a secure, randomly-generated share token — no sequential IDs, no scraping.

Real-Time View Tracking

Every open is logged with timestamp, IP, country, city, device, browser, OS, and exact view duration.

Visitor Analytics

See unique visitors, total views, average time on document, and per-view breakdowns.

Client Replies

Viewers can reply directly from the proposal page — name, email and message, no signup required.

Self-Manage Dashboard

Uploaders get a private manage link to toggle, edit, replace files, and download analytics.

Find My Proposals

OTP-verified email recovery — users retrieve all their past uploads with a one-time code.

$ Ad Slots

Configurable pre- and post-document ad placements with timed delay — monetize your traffic.

Admin Features

  • Beautiful, responsive admin dashboard with charts and KPIs
  • Total proposals, views, replies, unique visitors with week-over-week trends
  • Top-performing proposals leaderboard
  • Active / inactive toggle per proposal — disable any link instantly
  • Storage usage monitor
  • Full SMTP email configuration (with test email button)
  • Site branding: logo, favicon, colors, meta tags, contact email
  • Custom HTML injection (head, body, footer) — perfect for analytics, chat widgets, pixels
  • Built-in editor for Privacy Policy and Terms of Service pages
  • Admin password and profile management
  • One-time installer wizard (auto-locks after install)

Technical Highlights

  • Laravel 11.31 — modern, secure, well-maintained framework
  • Tailwind CSS 3.4 + Vite 6 — fast, beautiful, customizable UI
  • MySQL, MariaDB, PostgreSQL, or SQLite supported
  • Rate limiting on uploads, OTP requests, and OTP verification
  • CSRF, CSP headers, XSS sanitization, MIME validation
  • Private file storage — files never directly accessible by URL
  • cPanel-friendly: pre-configured root index.php + .htaccess
  • IP geolocation via free ip-api.com service (cached 30 days)
  • Built-in user-agent parser (no external dependency)

Server Requirements

ProposalTrack runs on any standard PHP hosting environment, including most shared hosts.

ComponentMinimumRecommended
PHP8.28.3+
DatabaseMySQL 5.7 / MariaDB 10.3 / PostgreSQL 10 / SQLiteMySQL 8.0 or MariaDB 10.6+
Web ServerApache (mod_rewrite) or NginxApache 2.4 / Nginx 1.20+
Memory128 MB PHP memory_limit256 MB+
Storage200 MB free + space for uploads1 GB+ depending on usage
SSLOptional (recommended)HTTPS via Let's Encrypt

Required PHP Extensions

Most hosts have these enabled by default. The web installer will check them for you.

  • pdo_mysql (or pdo_pgsql / pdo_sqlite)
  • openssl
  • mbstring
  • tokenizer
  • xml & ctype
  • json
  • bcmath
  • fileinfo
Optional Composer and Node.js / npm are not required to run the script — all dependencies are pre-bundled. You only need them if you want to customize and rebuild the front-end assets.

Web Installer (Recommended)

The fastest way to get ProposalTrack running. Works on most shared hosts and VPS environments.

  1. Upload the files Extract the ZIP archive and upload the contents of the proposaltrack/ folder to your web root (e.g. public_html, www, or your domain's document root).
  2. Create a database In your hosting control panel (cPanel, Plesk, etc.), create a new MySQL/MariaDB database and a user with full privileges on it. Note down the database name, username, and password.
  3. Set folder permissions Make sure these folders are writable by the web server (chmod 755 or 775):
    storage/
    storage/app/
    storage/framework/
    storage/logs/
    bootstrap/cache/
  4. Open the installer Visit your domain in the browser — e.g. https://yourdomain.com/. You'll be redirected automatically to the installer at /install.
  5. Step 1 — Requirements check The installer verifies PHP version, extensions, and folder permissions. Fix any red items before continuing.
  6. Step 2 — Database Enter your database host (usually localhost), database name, username, and password. The installer will test the connection and run all migrations automatically.
  7. Step 3 — Admin account Set the email, name, and password for your admin user. You'll use these to log in to the admin panel.
  8. Step 4 — Site settings Enter the site name and contact email. You can change these later.
  9. Step 5 — Done! The installer locks itself automatically. You can now log in at /admin/login.
Important After installation, the /install route returns a 404 automatically. There is no need to delete the installer files manually.

Manual Installation

For advanced users with SSH/CLI access who prefer command-line setup.

  1. Upload & extract Upload the archive to your server and extract it.
    unzip proposaltrack.zip
    cd proposaltrack
  2. Copy environment file
    cp .env.example .env
    php artisan key:generate
  3. Edit .env Set your database credentials and app URL:
    APP_NAME=ProposalTrack
    APP_URL=https://yourdomain.com
    
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=proposaltrack
    DB_USERNAME=your_db_user
    DB_PASSWORD=your_db_pass
  4. Run migrations
    php artisan migrate --force
    php artisan storage:link
  5. Create the admin user
    php artisan tinker
    >>> \App\Models\AdminUser::create([
            'email'    => 'admin@example.com',
            'name'     => 'Administrator',
            'password' => bcrypt('YourStrongPassword'),
        ]);
    >>> exit
  6. Mark installer as complete
    php artisan tinker
    >>> \App\Models\Setting::set('installed', '1');
    >>> exit
  7. (Optional) Cache config for production
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache

cPanel / Shared Hosting Notes

ProposalTrack is pre-configured to work seamlessly on cPanel-based hosting.

Detailed cPanel Guide Available For step-by-step instructions with screenshots and a full troubleshooting section, see the dedicated cPanel Installation Guide →

Unlike a standard Laravel app where you need to point your domain to the public/ folder, ProposalTrack ships with a root-level index.php and .htaccess that transparently delegate requests into the public folder. This means you can:

  • Upload everything directly to public_html (or a subdomain folder)
  • Skip any document-root configuration
  • Run the web installer immediately by visiting your domain

PHP Version

In cPanel, find Select PHP Version (or MultiPHP Manager) and ensure PHP 8.2 or higher is selected for the domain. Then enable the required extensions listed in Server Requirements.

File Permissions

Use the cPanel File Manager or an FTP client to set:

  • All directories: 755
  • All files: 644
  • Make sure storage/ and bootstrap/cache/ are writable.

After Installation

A short checklist to make sure your installation is production-ready.

  1. Log in to /admin/login using the admin credentials you set during installation.
  2. Visit Settings → Email and configure your SMTP server (see Email Setup).
  3. Send a test email to confirm SMTP is working.
  4. Upload your logo and favicon under Settings → Branding.
  5. Edit your Privacy Policy and Terms of Service from the Legal Pages section.
  6. Set APP_DEBUG=false in your .env file before going live.
  7. Set up the cron entry for OTP cleanup (see Cron / Scheduler).
  8. Install an SSL certificate (Let's Encrypt is free and works fine).

Admin Login

The admin login page is available at:

https://yourdomain.com/admin/login

Enter the email and password you created during installation. After three failed attempts, login is rate-limited for one minute to prevent brute-force attacks.

Forgot your password? From the server's command line, you can reset it via Tinker:
php artisan tinker
>>> $u = \App\Models\AdminUser::first();
>>> $u->password = bcrypt('NewPassword123');
>>> $u->save();

Admin Dashboard

Your home base for monitoring proposal activity at a glance.

The dashboard shows:

  • KPI cards — total proposals, total views, total replies, unique visitors
  • Trend indicators — week-over-week change for each metric
  • Active vs Inactive proposal counts
  • Storage usage — total disk space used by uploaded files
  • Recent uploads — the latest proposals submitted
  • Top performers — most-viewed proposals leaderboard
  • Charts — visualization of uploads and views over time

Manage Proposals

View, deactivate, and inspect every proposal uploaded to your platform.

Navigate to Admin → Proposals to see the full list.

Available actions

  • View details — opens a detail page with full visitor analytics, all views and replies
  • Toggle active/inactive — instantly disable or re-enable any share link
  • Delete — permanently removes the proposal, its file, and all tracking data
  • Filter & search — by title, uploader email, date, or status

On the proposal detail page you'll see a complete view log with timestamps, IP addresses, geolocation, device/browser, and time spent on each view. You can also see and manage client replies.

Settings

All site-wide configuration lives under Admin → Settings.

Settings are organized into clear tabs — each tab is documented in the Configuration section below.

Email (SMTP) Configuration

ProposalTrack sends emails for share confirmations, client reply notifications, and OTP verification.

Navigate to Settings → Email and fill in:

FieldDescriptionExample
SMTP HostYour provider's SMTP serversmtp.gmail.com
SMTP Port587 (TLS) or 465 (SSL)587
Encryptiontls / ssl / nonetls
UsernameYour SMTP loginnoreply@yourdomain.com
PasswordYour SMTP password / app password••••••••
From AddressSender email shown to recipientsnoreply@yourdomain.com
From NameSender display nameProposalTrack

After saving, click Send Test Email to verify everything works. The test will be sent to your admin email address.

Recommended providers Gmail (with App Password), SendGrid, Mailgun, Amazon SES, Postmark, or any standard SMTP service. For Gmail, you must enable 2-factor authentication and generate an App Password.
Avoid free Gmail for production Free Gmail accounts have low daily send limits and may flag bulk emails as spam. Use a dedicated transactional provider for any real-world deployment.

Site & Branding

Customize the look and meta information of your installation.

Under Settings → Site and Settings → Branding you can configure:

  • Site name — shown in the header, emails, and meta titles
  • Contact email — public-facing support email
  • Logo — PNG/SVG/JPG, ideally 200×60px
  • Favicon — ICO or PNG, 32×32px or 64×64px
  • Meta title, description, keywords — for SEO
  • Custom HTML — inject code into <head>, after <body>, or in the footer

Custom HTML injection is great for adding chat widgets (Tawk.to, Crisp, Intercom), Facebook Pixel, Hotjar, or any other third-party script.

File Upload Settings

Control what users can upload and how large files can be.

Under Settings → Uploads:

  • Maximum file size — in megabytes (default: 10 MB)
  • Allowed file types — comma-separated list (default: pdf,doc,docx)
PHP & web server limits Make sure your php.ini values for upload_max_filesize, post_max_size, and memory_limit are equal to or larger than the limit you set in the admin panel. On Nginx, also check client_max_body_size.

Ads & Monetization

Built-in ad slots for Google AdSense, banner ads, or any custom HTML.

Under Settings → Ads, two ad slots are available on every public proposal page:

  • Pre-document ad — shown before the proposal renders, with a configurable countdown delay
  • Post-document ad — shown below the proposal after the user finishes reading
  • Ad delay — the number of seconds to wait before showing the proposal (forces users to see the pre-ad)

Paste any valid HTML — AdSense unit, banner image, affiliate link, etc.

Google Analytics

Under Settings → Analytics, paste your Google Analytics Measurement ID (e.g. G-XXXXXXXXXX). The tracking snippet is automatically injected on every public page.

For more advanced tracking (GTM, Plausible, Fathom, custom pixels), use the Custom HTML — head field instead.

Uploading a Proposal

No account required — anyone can upload from the homepage.

  1. Visit the homepage at https://yourdomain.com/
  2. Drag & drop a PDF, DOC, or DOCX file (or click to browse)
  3. Enter a proposal title, optional description, and your email address
  4. Click Upload — the system stores the file and emails you the share & manage links

After upload, the user sees a confirmation page with the share link (to send to clients) and the manage link (to track activity later). Both links are also emailed to the uploader.

Sharing & Viewing

The share link looks like:

https://yourdomain.com/view/abc123def456...

When a recipient opens this link:

  • The proposal is rendered in a clean viewer (PDF embedded; DOC/DOCX served for download)
  • The view is logged with timestamp, IP, geolocation, device, browser, OS
  • The total time spent reading is tracked automatically
  • The viewer can submit a reply (name, email, message) without signing up

Managing Proposals

The manage link looks like:

https://yourdomain.com/manage/xyz789...

From the manage page, the uploader can:

  • See all views, replies, and analytics
  • Toggle the proposal active/inactive (disabling the share link)
  • Edit the title and description
  • Replace the uploaded file
  • Delete the proposal entirely
  • Delete individual replies
  • Download the original file

Finding Lost Proposals

If a user loses their manage link, they can recover all their uploads via OTP.

  1. Visit https://yourdomain.com/find-proposals
  2. Enter the email address used during upload
  3. Receive a 6-digit OTP code by email
  4. Enter the code to retrieve a list of all proposals uploaded with that email

OTPs expire after 15 minutes. Rate limits prevent abuse: 3 send requests and 5 verification attempts per email per 15 minutes.

Security

ProposalTrack is built with security as a first-class concern.

  • CSRF protection on all forms via Laravel's built-in middleware
  • Rate limiting on uploads (10/IP/hour), OTP send (3/email/15min), OTP verify (5/email/15min), and admin login (3 attempts/min)
  • Content Security Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy headers on all responses
  • Input sanitization — all user input is stripped of HTML tags and validated
  • MIME validation on uploads — file type checked from actual content, not just extension
  • SQL injection protection via Eloquent ORM and parameterized queries
  • Private file storage — uploaded files are stored outside the public web root and served only via token-protected routes
  • Bcrypt password hashing for admin accounts
  • Secure random tokens for share and manage links (64 chars, cryptographically random)
  • Installer auto-locks after first run, preventing accidental re-installation
Production checklist Before going live, set APP_DEBUG=false, install an SSL certificate, use a strong admin password, and configure regular backups for your database and storage/ folder.

Cron / Scheduler

Optional but recommended for keeping the database tidy.

ProposalTrack ships a single scheduled command that cleans up expired OTP records once per day. To enable it, add the following entry to your server's crontab:

* * * * * cd /path/to/proposaltrack && php artisan schedule:run >> /dev/null 2>&1

On cPanel, add this entry under Cron Jobs → Add New Cron Job with the schedule set to "every minute".

You can also run the cleanup manually:

php artisan proposaltrack:cleanup
Not strictly required OTP records are small and do not affect performance — the cleanup is a hygiene task, not a critical dependency. The script will run perfectly fine without it.

Troubleshooting

"500 Internal Server Error" after install

  • Check that storage/ and bootstrap/cache/ are writable (chmod 755 or 775)
  • Confirm PHP 8.2+ is selected for the domain
  • Check the .env file exists and has a valid APP_KEY
  • Look at storage/logs/laravel.log for the actual error

"No application encryption key has been specified"

Run from CLI: php artisan key:generate — or copy the value from .env.example and re-run the installer.

404 on every page except homepage

Your web server is missing rewrite rules. On Apache, ensure mod_rewrite is enabled and the bundled .htaccess file is present. On Nginx, add the standard Laravel rewrite block:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Email is not being sent

  • Verify SMTP credentials in Settings → Email
  • Click Send Test Email — the error message will tell you exactly what's wrong
  • For Gmail, generate an App Password (regular password will not work with 2FA)
  • Check your hosting provider hasn't blocked outbound SMTP ports (587/465)

File uploads fail silently

  • Increase upload_max_filesize and post_max_size in php.ini
  • On Nginx, increase client_max_body_size
  • Check the limit in Settings → Uploads matches or is below the PHP limit
  • Ensure storage/app/public/uploads is writable

Geolocation shows "Unknown"

The script uses the free ip-api.com service. If your server is firewalled or rate-limited, results may be empty. Geolocation is purely cosmetic and does not affect functionality.

Forgot admin password

See the Admin Login section for a CLI reset using Tinker.

I want to re-run the installer

Connect to your database, open the settings table, and delete the row where key = 'installed'. The installer will be available again.

Changelog

Version 1.0.0 — Initial release

  • Core upload, share, view, and tracking workflow
  • Admin dashboard with analytics, charts, and KPI cards
  • Admin proposal management (list, view, toggle, delete)
  • SMTP-based email with test sending
  • OTP-verified "Find My Proposals" recovery flow
  • Configurable ads, branding, meta tags, and custom HTML injection
  • Built-in editor for Privacy Policy and Terms of Service
  • 5-step web installer wizard
  • cPanel-friendly file structure
  • Rate limiting, CSRF, CSP, and input sanitization throughout
  • IP geolocation and user-agent parsing

Support & Credits

Need help? We're here for you.

Getting support

Please use the support channel on the Codester product page. Include the following information when you submit a ticket:

  • Your Codester purchase ID
  • PHP version (run php -v or check cPanel)
  • Hosting environment (cPanel, Plesk, VPS, etc.)
  • A clear description of the issue
  • Any error messages from storage/logs/laravel.log
  • Screenshots if relevant

Built with

  • Laravel 11 — laravel.com
  • Tailwind CSS 3.4 — tailwindcss.com
  • Vite 6 — vitejs.dev
  • ip-api.com — IP geolocation (free tier)
Thank you! Thanks for purchasing ProposalTrack. If you enjoy the script, please leave a 5-star review on Codester — it really helps us continue building and improving!