What We Are Finishing in Part 6
The application is built, but a working development version is not the same thing as a launch-ready store. This final chapter checks the entire system as one connected business workflow.
Complete Testing
- Catalog and product pages
- Variant selection
- Checkout and fulfillment
- Failure states
Security
- Sessions and CSRF
- Uploads and permissions
- Private credentials
- Safe error handling
Performance
- Image optimization
- Database efficiency
- Browser caching
- Asset delivery
Launch Operations
- SEO validation
- Backups
- Monitoring
- Post-launch maintenance
It is the point where real customers, real traffic, real orders, and real platform changes begin testing assumptions.
Contents
- The launch process
- Separate development and production
- Configure production error handling
- Secure sessions, headers, and uploads
- Review database performance
- Optimize storefront images
- Add browser caching
- Validate product-page SEO
- Build the sitemap and robots.txt
- Test checkout and fulfillment
- Create automated backups
- Add monitoring and health checks
- Use a staged launch
- Post-launch maintenance
- Final launch checklist
- Frequently asked questions
The Launch Process
Verify Every Workflow
Test storefront behavior, admin tools, APIs, checkout, shipping, tax, and fulfillment.
Secure the Application
Review credentials, sessions, permissions, uploads, admin actions, and error handling.
Improve Delivery
Reduce image weight, database work, blocking assets, and repeated external requests.
Monitor Real Usage
Release gradually, watch logs and orders, and fix real-world problems quickly.
Separate Development and Production
Safe Place to Break Things
Stable Customer Environment
Configure Production Error Handling
<?php
ini_set('display_errors', '0');
ini_set('display_startup_errors', '0');
ini_set('log_errors', '1');
ini_set(
'error_log',
__DIR__ . '/../private/logs/application.log'
);
error_reporting(E_ALL);
set_exception_handler(
static function (Throwable $exception): void {
$requestId = bin2hex(
random_bytes(8)
);
error_log(
sprintf(
'[%s] %s in %s:%d%s%s',
$requestId,
$exception->getMessage(),
$exception->getFile(),
$exception->getLine(),
PHP_EOL,
$exception->getTraceAsString()
)
);
http_response_code(500);
echo 'The store encountered an error. Reference: ' .
htmlspecialchars(
$requestId,
ENT_QUOTES,
'UTF-8'
);
}
);
Secure Sessions, Headers, and Uploads
<?php
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
ini_set('session.use_strict_mode', '1');
ini_set('session.use_only_cookies', '1');
session_start();
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');
header('X-Frame-Options: SAMEORIGIN');
if (!empty($_SERVER['HTTPS'])) {
header(
'Strict-Transport-Security: max-age=31536000; includeSubDomains'
);
}
- Validate uploaded MIME type and actual image decoding.
- Limit upload size and image dimensions.
- Generate safe filenames rather than trusting uploaded names.
- Prevent script execution inside upload directories.
- Keep API tokens and database credentials outside public_html.
- Use CSRF protection on every state-changing form.
Review Database Performance
EXPLAIN
SELECT
item_number,
title,
line,
short_description,
price,
likes
FROM shirts
WHERE active = 1
AND line = 'The American Slice'
ORDER BY item_number DESC
LIMIT 24;
- Select only the columns needed by the page.
- Avoid one additional query for every product card.
- Index active status, collection, item number, and foreign keys.
- Paginate catalog results.
- Use local data instead of external API requests on page load.
Optimize Storefront Images
| Image Type | Purpose | Handling |
|---|---|---|
| Production artwork | Printing | Keep full resolution and separate from web files |
| Catalog thumbnail | Product grid | Use a smaller square WebP or AVIF copy |
| Product gallery | Detailed view | Use responsive dimensions and modern compression |
| Open Graph image | Social sharing | Use a dedicated 1200 × 630 image |
<picture>
<source
srcset="/images/1001/catalog.avif"
type="image/avif"
>
<source
srcset="/images/1001/catalog.webp"
type="image/webp"
>
<img
src="/images/1001/catalog.jpg"
alt="Bigfoot barber graphic T-shirt"
width="900"
height="900"
loading="lazy"
decoding="async"
>
</picture>
Add Browser Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
Validate Product-Page SEO
Clear Product Topic
- Unique title and H1
- Useful product copy
- Collection context
- Internal links
Stable URLs
- Canonical URL
- Consistent product URL
- Real 404 responses
- No duplicate parameter pages
Useful Context
- Descriptive filenames
- Accurate alt text
- Open Graph image
- Fast delivery
Machine-Readable Data
- Meta description
- Product structured data
- Breadcrumb structured data
- Social metadata
Build the Sitemap and robots.txt
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /manage/
Disallow: /api/
Sitemap: https://theconspiracyshirtcompany.com/sitemap.xml
Test Checkout and Fulfillment End to End
- The correct product, color, and size appear in checkout.
- The Shopify price matches the storefront price.
- Discount codes and free-shipping rules work correctly.
- Tax and shipping behavior are correct.
- The order reaches Printify with the right variant and artwork.
- Confirmation and tracking emails are delivered.
Create Automated Backups
#!/usr/bin/env bash
set -euo pipefail
BACKUP_ROOT="$HOME/store-backups"
STAMP="$(date -u +%Y-%m-%d_%H-%M-%S)"
BACKUP_DIR="$BACKUP_ROOT/$STAMP"
mkdir -p "$BACKUP_DIR"
mysqldump --single-transaction --quick --lock-tables=false -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" | gzip > "$BACKUP_DIR/database.sql.gz"
tar -czf "$BACKUP_DIR/product-images.tar.gz" "$HOME/public_html/images"
find "$BACKUP_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;
Add Monitoring and Health Checks
<?php
/**
* /health.php
*/
declare(strict_types=1);
require_once __DIR__ . '/../private/connection.php';
header(
'Content-Type: application/json; charset=utf-8'
);
header('Cache-Control: no-store');
$status = [
'ok' => true,
'time' => gmdate('c'),
'database' => false,
];
try {
$pdo->query('SELECT 1');
$status['database'] = true;
} catch (Throwable $exception) {
$status['ok'] = false;
error_log(
'Health check failed: ' .
$exception->getMessage()
);
}
http_response_code(
$status['ok'] ? 200 : 503
);
echo json_encode(
$status,
JSON_UNESCAPED_SLASHES
);
Use a Staged Launch
Test with the Store Team
Complete orders and test admin workflows before inviting outside traffic.
Soft Launch
Send a small amount of traffic and watch orders, logs, questions, and fulfillment.
Expand Promotion
Increase traffic after the complete order workflow has been confirmed.
Post-Launch Maintenance
Operational Checks
Review new orders, checkout failures, sync errors, unavailable products, and customer messages.
Store Health
Review backups, logs, broken links, page speed, search traffic, and failed jobs.
Platform Review
Review API changes, PHP updates, database growth, security, pricing, and providers.
Improve from Real Data
Use search terms, clicks, likes, purchases, reviews, and support questions to improve the store.
Final Launch Checklist
- Development and production configurations are separate.
- Production errors are logged but not displayed publicly.
- Private credentials remain outside the public web root.
- HTTPS is enforced across the store.
- Admin pages require authentication and authorization.
- State-changing actions use CSRF protection.
- PHP sessions use secure cookie settings.
- Image uploads validate type, size, and dimensions.
- Database queries use prepared statements.
- Catalog filters and relationships are indexed.
- Catalog results are paginated.
- Product images are compressed and correctly sized.
- Production artwork is separate from web images.
- Static assets use caching and cache busting.
- Product titles, descriptions, and canonical URLs are unique.
- Missing products return a true 404 response.
- Product and breadcrumb structured data validate.
- The XML sitemap includes active products and guides.
- Internal links and image paths have been checked.
- Color and size selections map to the correct Shopify variant.
- Shipping, discounts, taxes, and prices have been tested.
- A complete Shopify-to-Printify test order has been completed.
- Database and file backups run automatically.
- A backup restore has been tested.
- Application and API errors are monitored.
- Health checks detect site or database failures.
- The store has been tested on mobile and desktop.
- The launch begins with a limited audience.
- Post-launch maintenance responsibilities are documented.
Launch and Optimization FAQ
What should be tested before launching a custom T-shirt store?
Test catalog filters, product pages, images, color and size selection, variant mappings, Shopify cart creation, checkout, discounts, shipping, taxes, Printify fulfillment, emails, mobile layouts, admin tools, and failure states.
How should PHP errors be handled in production?
Disable display_errors for visitors, enable error logging, store logs outside the public web root, return safe customer-facing messages, and monitor the logs regularly.
What should be backed up?
Back up the MySQL database, product images, production artwork, private configuration, important scripts, and deployment files. Keep at least one copy outside the hosting account.
How can a custom PHP store load faster?
Optimize images, use modern image formats, add browser caching, compress text assets, reduce database queries, add indexes, paginate catalogs, defer noncritical JavaScript, and use server caching where appropriate.
What SEO elements should every product page include?
Use a unique title, meta description, canonical URL, descriptive heading, useful product copy, image alt text, Open Graph metadata, product structured data, breadcrumbs, and internal links.
Should API requests run during normal product-page loads?
Usually no. Product pages should use local database data. Shopify and Printify API requests should happen during checkout, synchronization, publishing, or administration workflows.
How should uploaded images be secured?
Validate MIME type and actual image decoding, limit file size and dimensions, generate safe filenames, prevent script execution in upload directories, and never trust a filename extension alone.
How do I know when an external integration fails?
Record API status codes, request IDs when available, timestamps, product identifiers, retry counts, and safe summaries in private logs. Add admin dashboard warnings for failed or stale jobs.
Should the entire store be launched at once?
A staged launch is safer. Test privately, launch to a small audience, monitor errors and orders, then expand traffic after checkout, fulfillment, and operational workflows are confirmed.
What should happen after launch?
Continue monitoring logs, page speed, search visibility, broken links, checkout completion, failed synchronizations, unavailable variants, image issues, backups, API changes, and customer feedback.
You Now Have a Store You Can Actually Run
This series started with a simple idea: keep the storefront under your control, let Shopify handle checkout, let Printify handle fulfillment, and build small tools for everything in between.
By the end, the store is no longer just a few PHP pages connected to a database. It has a product catalog, dynamic product pages, variant mapping, checkout, synchronization, pricing controls, image workflows, admin tools, backups, monitoring, and a process for finding problems before customers do.
More importantly, it is built around the way the business actually works. New tools can be added when a task becomes repetitive. New product types can be added without rebuilding the storefront. Platforms can change without forcing the entire site to change with them.
Products change. APIs change. Search engines change. Something eventually breaks for a reason nobody predicted. The goal was not to build a system that never needs attention. The goal was to build one that can be understood, repaired, and improved without starting over.
What Comes Next
Launch it carefully. Watch what customers click. Pay attention to the tasks you keep repeating. When something takes too long, turns into a spreadsheet, or requires the same five steps every week, that is probably the next tool to build.
That is how this store grew, and it is probably how yours will grow too: one real problem, one useful fix, and one less thing to do by hand.