General Guide: See Global LCP Guide for universal concepts and fixes.
What is LCP?
Largest Contentful Paint measures when the largest content element becomes visible. Google recommends LCP under 2.5 seconds. CMS Made Simple (CMSMS) uses the Smarty template engine with a MySQL backend, so LCP depends on Smarty template caching, module query performance, and theme asset loading.
CMSMS-Specific LCP Causes
- Smarty template compilation on every request -- without caching, CMSMS compiles Smarty templates from scratch, adding 200-800ms to TTFB
- Module overhead -- each active module (News, Gallery, FormBuilder) runs PHP and database queries on page load even if not used on that page
- No built-in image processing -- uploaded images serve at original resolution from
uploads/images/ - Render-blocking module CSS/JS -- modules inject their own stylesheets and scripts into
{cms_head_css}and{cms_head_js}tags synchronously - Shared hosting limitations -- CMSMS is commonly deployed on cheap shared hosting with slow PHP execution
Fixes
1. Enable Smarty Template Caching
Configure CMSMS to cache compiled Smarty templates. In config.php:
// config.php -- enable Smarty caching
$config['smarty_caching'] = true;
$config['smarty_cache_lifetime'] = 3600; // 1 hour
// Also enable content caching in Admin > Global Settings > Performance
// Set "Cache content" to Yes
// Set "Cache template compilations" to Yes
Additionally, enable CMSMS's built-in page caching at Admin > Extensions > Page Caching:
// Or via config.php
$config['page_cache'] = true;
$config['page_cache_expiry'] = 3600;
2. Optimize Images Before Upload
CMSMS has no image processing pipeline. Use server-side optimization or pre-process before uploading:
# Server-side: optimize all uploaded images
find uploads/images/ -name "*.jpg" -exec mogrify -strip -quality 80 -resize "1920>" {} \;
find uploads/images/ -name "*.png" -exec optipng -o2 {} \;
In your Smarty template, add responsive image attributes:
{* In your page template *}
{if $content_obj->GetPropertyValue('hero_image')}
<img
src="{uploads_url}/images/{$content_obj->GetPropertyValue('hero_image')}"
width="1200" height="630"
alt="{$content_obj->Name()|cms_escape}"
loading="eager"
fetchpriority="high"
style="aspect-ratio: 1200/630; width: 100%; height: auto; object-fit: cover;"
>
{/if}
3. Reduce Module Load Overhead
Disable unused modules at Admin > Extensions > Modules. Common heavy modules to audit:
- News -- runs database queries even on non-news pages if loaded globally
- Gallery/Album -- loads jQuery plugins on every page
- FormBuilder -- injects validation scripts site-wide
For modules you keep, use conditional loading in templates:
{* Only load Gallery assets on gallery pages *}
{if $page_alias == 'gallery'}
{Gallery action='default' ...}
{/if}
4. Consolidate and Defer Theme Assets
CMSMS modules inject CSS/JS via {cms_head_css} and {cms_head_js}. Optimize your layout template:
{* In your layout template *}
<head>
{* Inline critical CSS *}
<style>
.header { display: flex; height: 64px; }
.hero { width: 100%; aspect-ratio: 16/9; }
body { font-family: system-ui, sans-serif; margin: 0; }
</style>
{* Preload hero image on homepage *}
{if $page_alias == 'home'}
<link rel="preload" as="image" href="{uploads_url}/images/hero.jpg">
{/if}
{* Load module CSS but defer non-critical *}
{cms_head_css}
</head>
<body>
{content}
{* Move JS to bottom and add defer *}
{cms_head_js}
<script defer src="{root_url}/themes/{$gCms->GetConfig()->smarty_cachedir}/../yourtheme/js/theme.js"></script>
</body>
5. Add Server-Level Caching
Configure .htaccess for asset caching:
# .htaccess in CMSMS root
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
</IfModule>
Measuring LCP on CMSMS
- CMSMS Admin > Extensions > Page Caching -- check cache hit rates to see how often pages are served from cache
- PageSpeed Insights -- test homepage, content pages, and any pages using heavy modules (Gallery, News)
- TTFB check --
curl -w "TTFB: %{time_starttransfer}\n" -o /dev/null -s https://yoursite.com-- if over 800ms, focus on caching before frontend optimization - PHP profiling -- if you have access, use Xdebug or Blackfire to profile which modules consume the most execution time
Analytics Script Impact
CMSMS analytics are typically added via the CGSmartImage or custom User Defined Tags (UDTs):
- Ensure any analytics UDT outputs
asyncordeferattributes on script tags - If using the Google Analytics module from the Forge, verify it outputs async gtag.js
- Place tracking code in the layout template after
{content}rather than in<head>