# Shortlink Feature - Deployment Guide

## Overview

Shortlink dashboard dengan custom Open Graph (OG) Meta Tags untuk Facebook preview optimization telah berhasil ditambahkan ke Domain Dashboard.

**Fitur Utama:**
- ✅ Short URL management (create, read, delete)
- ✅ Custom OG meta tags (title, description, image)
- ✅ Facebook/Twitter/LinkedIn preview optimization
- ✅ Click tracking & analytics
- ✅ Clean URLs dengan .htaccess rewrite (`/s/abc123`)
- ✅ Bot detection untuk crawler optimization
- ✅ Auto-redirect dengan preview page

## Files Created/Modified

### Database Schema
- `database-migrations/002_create_shortlinks_table.sql` - Shortlinks table schema

### Backend (Repository & Service Layer)
- `src/Repository/ShortlinkRepository.php` - Data access layer
- `src/Service/ShortlinkService.php` - Business logic & validation
- `bootstrap/init.php` - Added shortlink service initialization

### AJAX Endpoints
- `public/ajax/submit-shortlink.php` - Create shortlink
- `public/ajax/get-shortlinks.php` - Get shortlinks with filters
- `public/ajax/delete-shortlink.php` - Delete shortlink
- `public/ajax/update-shortlink.php` - Update shortlink (future use)

### Redirect Handler
- `public/s.php` - Redirect handler dengan OG meta tags
- `public/.htaccess` - Added rewrite rules untuk clean URLs

### Frontend (Dashboard UI)
- `public/index.php` - Added Shortlinks tab + JavaScript handlers

## Deployment Steps

### 1. Database Migration

Import the shortlinks table schema:

```bash
# Via MySQL CLI
mysql -u username -p database_name < database-migrations/002_create_shortlinks_table.sql

# Or via phpMyAdmin
# 1. Login ke phpMyAdmin
# 2. Select database
# 3. Go to Import tab
# 4. Choose file: database-migrations/002_create_shortlinks_table.sql
# 5. Click "Go"
```

**Verify Table Created:**
```sql
SHOW TABLES LIKE 'shortlinks';
DESCRIBE shortlinks;
```

### 2. Test Database Connection

```bash
# Test basic PHP connection
php -r "
\$pdo = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
\$stmt = \$pdo->query('SELECT COUNT(*) FROM shortlinks');
echo 'Shortlinks count: ' . \$stmt->fetchColumn();
"
```

### 3. Verify File Permissions

```bash
# For cPanel/shared hosting
chmod 644 public/s.php
chmod 644 public/ajax/submit-shortlink.php
chmod 644 public/ajax/get-shortlinks.php
chmod 644 public/ajax/delete-shortlink.php
chmod 644 public/ajax/update-shortlink.php

# Verify .htaccess readable
chmod 644 public/.htaccess
```

### 4. Test Rewrite Rules

**Test Clean URL Redirect:**
```bash
# Should redirect to s.php?slug=test
curl -I http://yourdomain.com/s/test

# Expected: HTTP 200 (if 'test' shortlink exists) or 404 (if not exists)
```

**If rewrite not working:**
```bash
# Check if mod_rewrite enabled
php -r "phpinfo();" | grep -i mod_rewrite

# Or check via test page
echo "<?php phpinfo(); ?>" > public/info.php
# Then access: http://yourdomain.com/info.php
# Search for "mod_rewrite"
```

### 5. Access Dashboard

Navigate to: `http://yourdomain.com/` and click **Shortlinks** tab.

You should see:
- Create Shortlink form (left side)
- Shortlinks list with analytics (right side)
- Analytics summary cards (Total Links, Active, Total Clicks, Avg CTR)

## Testing Guide

### 1. Create Test Shortlink

**Via Dashboard:**
1. Go to Shortlinks tab
2. Fill form:
   - **Destination URL:** `https://facebook.com`
   - **Custom Slug:** `fb-test` (or leave empty for random)
   - **OG Title:** `Test Facebook Preview`
   - **OG Description:** `This is a test shortlink for Facebook preview optimization`
   - **OG Image:** `https://via.placeholder.com/1200x630.png?text=Test+Image`
3. Click "Create Shortlink"
4. Short URL will be copied to clipboard automatically

**Via cURL (API test):**
```bash
curl -X POST http://yourdomain.com/ajax/submit-shortlink.php \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "csrf_token=YOUR_CSRF_TOKEN" \
  -d "destination_url=https://facebook.com" \
  -d "slug=fb-test" \
  -d "og_title=Test Facebook Preview" \
  -d "og_description=This is a test shortlink" \
  -d "og_image=https://via.placeholder.com/1200x630"
```

### 2. Test Redirect

**Via Browser:**
```
http://yourdomain.com/s/fb-test
```

Expected:
- See redirect preview page (monochrome design)
- After 0 seconds, auto-redirect to `https://facebook.com`
- Click count incremented

**Via cURL:**
```bash
curl -I http://yourdomain.com/s/fb-test

# Expected headers:
# HTTP/1.1 200 OK
# Content-Type: text/html; charset=UTF-8
# (HTML with OG meta tags)
```

### 3. Test OG Meta Tags (Facebook Debugger)

**Facebook Sharing Debugger:**
1. Go to: https://developers.facebook.com/tools/debug/
2. Enter your short URL: `http://yourdomain.com/s/fb-test`
3. Click "Debug"

**Expected Results:**
- **Title:** "Test Facebook Preview"
- **Description:** "This is a test shortlink for Facebook preview optimization"
- **Image:** https://via.placeholder.com/1200x630.png?text=Test+Image
- **Type:** website
- **URL:** http://yourdomain.com/s/fb-test

**If preview not showing:**
- Click "Scrape Again" button
- Wait 30 seconds and try again
- Check if OG image URL is publicly accessible
- Verify HTTPS/HTTP protocol

**Twitter Card Validator:**
1. Go to: https://cards-dev.twitter.com/validator
2. Enter: `http://yourdomain.com/s/fb-test`
3. Click "Preview card"

**LinkedIn Post Inspector:**
1. Go to: https://www.linkedin.com/post-inspector/
2. Enter: `http://yourdomain.com/s/fb-test`
3. Click "Inspect"

### 4. Test Click Tracking

```bash
# Make 5 requests to shortlink
for i in {1..5}; do
  curl -s http://yourdomain.com/s/fb-test > /dev/null
  echo "Click $i tracked"
  sleep 1
done

# Check analytics in dashboard
# Go to Shortlinks tab → should see "5" clicks
```

### 5. Test Delete Shortlink

1. Go to Shortlinks tab
2. Find `fb-test` shortlink
3. Click trash icon
4. Confirm deletion
5. Verify removed from list
6. Test URL returns 404: `http://yourdomain.com/s/fb-test`

## Production Considerations

### Security

**CSRF Protection:**
- ✅ All POST endpoints validate CSRF token
- ✅ Token rotated after critical operations
- ✅ hash_equals() used for timing-safe comparison

**SQL Injection Prevention:**
- ✅ All queries use prepared statements
- ✅ Zero string concatenation in SQL
- ✅ PDO::ATTR_EMULATE_PREPARES = false

**XSS Prevention:**
- ✅ All output escaped with htmlspecialchars()
- ✅ ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5 flags
- ✅ JSON_HEX_* flags for JavaScript context

**Input Validation:**
- ✅ Slug: alphanumeric + dash + underscore only (regex)
- ✅ URL: filter_var() + scheme whitelist (http/https)
- ✅ Length limits enforced (slug: 2-100, title: 255)

### Performance

**Database Indexes:**
```sql
-- Already created in migration
UNIQUE KEY uk_slug (slug)
INDEX idx_status_created (status, created_at DESC)
INDEX idx_destination_url (destination_url(255))
INDEX idx_click_count (click_count DESC)
```

**Query Optimization:**
- Pagination support (LIMIT/OFFSET)
- Filtered queries use indexes
- Click tracking non-blocking (try-catch with silent fail)

**Caching Recommendations:**
```php
// Future enhancement: APCu cache for hot shortlinks
$cacheKey = "shortlink:slug:{$slug}";
if (apcu_exists($cacheKey)) {
    $shortlink = apcu_fetch($cacheKey);
} else {
    $shortlink = $shortlinkRepo->findBySlug($slug);
    apcu_store($cacheKey, $shortlink, 300); // 5 min TTL
}
```

### Monitoring

**Key Metrics to Track:**
- Total shortlinks created per day
- Click-through rate (CTR) per shortlink
- Top performing shortlinks
- Failed redirect attempts (404 rate)
- Bot vs human traffic ratio

**Log Analysis:**
```bash
# Find all 404s on shortlinks
grep "s\.php.*404" /var/log/apache2/access.log

# Top shortlinks by traffic
grep "GET /s/" /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20

# Bot detection rate
grep "facebookexternalhit\|Twitterbot\|LinkedInBot" /var/log/apache2/access.log | wc -l
```

### Backup & Recovery

**Database Backup:**
```bash
# Backup shortlinks table
mysqldump -u user -p database_name shortlinks > shortlinks_backup_$(date +%Y%m%d).sql

# Restore from backup
mysql -u user -p database_name < shortlinks_backup_20250126.sql
```

**Configuration Backup:**
```bash
# Backup critical files
tar -czf shortlink_feature_backup.tar.gz \
  database-migrations/002_create_shortlinks_table.sql \
  src/Repository/ShortlinkRepository.php \
  src/Service/ShortlinkService.php \
  public/s.php \
  public/ajax/*shortlink*.php
```

## Troubleshooting

### Issue: Shortlinks not loading in dashboard

**Symptoms:** Spinner keeps loading, no shortlinks displayed

**Solutions:**
```bash
# 1. Check database table exists
mysql -u user -p -e "USE database_name; SHOW TABLES LIKE 'shortlinks';"

# 2. Check AJAX endpoint accessible
curl http://yourdomain.com/ajax/get-shortlinks.php

# 3. Check browser console for errors
# Open browser DevTools (F12) → Console tab
# Look for AJAX errors or CORS issues

# 4. Verify bootstrap/init.php initialized shortlink service
grep -n "shortlinkService" bootstrap/init.php
```

### Issue: Redirect not working (404 on /s/slug)

**Symptoms:** Accessing `/s/test` returns 404

**Solutions:**
```bash
# 1. Check .htaccess rewrite rules
cat public/.htaccess | grep -A 3 "Shortlink Handler"

# 2. Test if mod_rewrite enabled
php -r "phpinfo();" | grep -i "mod_rewrite"

# 3. Check s.php file exists and readable
ls -la public/s.php

# 4. Test direct access
curl http://yourdomain.com/s.php?slug=test

# 5. Enable RewriteLog (Apache 2.2)
# Add to .htaccess:
# RewriteLog "/tmp/rewrite.log"
# RewriteLogLevel 3

# 6. Check AllowOverride setting (Apache config)
# Ensure AllowOverride All or FileInfo
grep -r "AllowOverride" /etc/apache2/
```

### Issue: OG meta tags not showing in Facebook

**Symptoms:** Facebook Debugger shows no preview or wrong data

**Solutions:**
```bash
# 1. View page source and verify meta tags present
curl -s http://yourdomain.com/s/test | grep -i "og:"

# Expected output:
# <meta property="og:title" content="...">
# <meta property="og:description" content="...">
# <meta property="og:image" content="...">

# 2. Check OG image URL accessible
curl -I https://your-image-url.com/image.jpg
# Expected: HTTP 200

# 3. Verify image size (1200x630 recommended)
# Use Facebook Image Debugger or:
curl -s https://your-image-url.com/image.jpg | file -
# Should show: JPEG image data, 1200 x 630

# 4. Clear Facebook cache
# Go to: https://developers.facebook.com/tools/debug/
# Enter URL and click "Scrape Again"

# 5. Check if bot detected properly
curl -A "facebookexternalhit/1.1" http://yourdomain.com/s/test
# Should return HTML with OG tags (not redirect immediately)
```

### Issue: Click tracking not working

**Symptoms:** Click count stays at 0

**Solutions:**
```sql
-- 1. Check if click_count column exists
DESCRIBE shortlinks;

-- 2. Manually test increment
UPDATE shortlinks SET click_count = click_count + 1 WHERE slug = 'test';
SELECT click_count FROM shortlinks WHERE slug = 'test';

-- 3. Check for errors in PHP error log
tail -f /var/log/apache2/error.log | grep shortlink

-- 4. Test tracking function directly
php -r "
require 'bootstrap/init.php';
\$result = \$shortlinkService->trackClick(1);
var_dump(\$result);
"
```

### Issue: Random slug generation fails

**Symptoms:** Error "Failed to create shortlink" when leaving slug empty

**Solutions:**
```php
// Check if generateRandomSlug() working
php -r "
require 'bootstrap/init.php';
\$slug = \$shortlinkService->generateRandomSlug(6);
echo 'Generated: ' . \$slug . PHP_EOL;
"

// Test collision detection
php -r "
require 'bootstrap/init.php';
for (\$i = 0; \$i < 10; \$i++) {
    echo \$shortlinkService->generateRandomSlug(6) . PHP_EOL;
}
"
```

## Feature Roadmap

### Planned Enhancements

**1. Advanced Analytics (v2.0)**
- QR code generation for shortlinks
- Geographic click distribution (IP → Country)
- Referrer tracking (where clicks came from)
- Device detection (mobile/desktop/bot)
- Time-series analytics (clicks over time chart)

**2. Shortlink Expiration (v2.1)**
- Auto-expire shortlinks after N days
- Schedule expiration datetime
- Expired shortlink custom message page

**3. Custom Domains (v2.2)**
- Use custom domain for shortlinks (e.g., `short.yourdomain.com`)
- Per-domain branded shortlinks
- Domain-level analytics

**4. A/B Testing (v2.3)**
- Multiple destinations per slug (round-robin)
- Split traffic percentage
- Conversion tracking

**5. API Access (v2.4)**
- RESTful API for shortlink creation
- API key authentication
- Rate limiting per API key

## Support & Resources

**Facebook Open Graph Documentation:**
- https://developers.facebook.com/docs/sharing/webmasters/

**Twitter Card Documentation:**
- https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards

**LinkedIn Post Inspector:**
- https://www.linkedin.com/post-inspector/

**OG Image Best Practices:**
- Recommended size: 1200x630 pixels
- Aspect ratio: 1.91:1
- Format: JPG, PNG, or WebP
- Max file size: 8 MB
- Avoid text-heavy images (mobile preview)

**Testing Tools:**
- Facebook Debugger: https://developers.facebook.com/tools/debug/
- Twitter Card Validator: https://cards-dev.twitter.com/validator
- LinkedIn Inspector: https://www.linkedin.com/post-inspector/
- WhatsApp Preview: Send link to yourself on WhatsApp
- Telegram Preview: Send link to yourself on Telegram

## Changelog

**v1.0.0 (2025-12-26)**
- Initial release
- Shortlink CRUD operations
- Custom OG meta tags support
- Click tracking & analytics
- Facebook/Twitter/LinkedIn preview optimization
- Clean URLs with .htaccess rewrite
- Bot detection for crawler optimization
- Monochrome dashboard UI
- Copy to clipboard functionality

---

**Version:** 1.0.0
**Last Updated:** 2025-12-26
**Maintained By:** Domain Dashboard Team
