SilverStripe is a flexible, open-source CMS and framework built on PHP. It's popular in Australia, New Zealand, and government sectors, offering enterprise-grade content management with developer-friendly architecture.
Available Integrations
Analytics Platforms
- SilverStripe module installation
- DataObject tracking
- CMS user exclusion
- Elemental block analytics
Tag Management
- GTM module configuration
- Data layer for SilverStripe pages
- Content block tracking
- Form submission events
Marketing Pixels
SilverStripe-Specific Integration Considerations
ORM-Based Architecture
SilverStripe uses an object-relational mapping system:
- DataObjects: Content stored as database records
- Page Types: Custom page classes with fields
- Elemental Blocks: Modular content components
- Versioned Content: Draft/published workflow
Template Integration
Implement tracking via SilverStripe templates:
<%-- In templates/Includes/Analytics.ss --%>
<% if $SiteConfig.GoogleAnalyticsID %>
<script async src="https://www.googletagmanager.com/gtag/js?id={$SiteConfig.GoogleAnalyticsID}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{$SiteConfig.GoogleAnalyticsID}', {
page_id: '{$ID}',
page_title: '{$Title.JS}',
page_type: '{$ClassName}',
<% if $Author %>
author: '{$Author.Title.JS}',
<% end_if %>
<% if $Categories.exists %>
categories: '{$Categories.Column("Title").implode(",")}'
<% end_if %>
});
</script>
<% end_if %>
DataExtension for Analytics
Extend pages with analytics data:
<?php
// app/src/Extensions/AnalyticsPageExtension.php
namespace App\Extensions;
use SilverStripe\ORM\DataExtension;
use SilverStripe\View\Requirements;
class AnalyticsPageExtension extends DataExtension
{
public function getAnalyticsData(): array
{
return [
'page_id' => $this->owner->ID,
'page_title' => $this->owner->Title,
'page_type' => $this->owner->ClassName,
'page_url' => $this->owner->AbsoluteLink(),
'last_edited' => $this->owner->LastEdited,
'created' => $this->owner->Created,
];
}
public function contentControllerInit($controller)
{
if (!$this->owner->config()->get('exclude_from_analytics')) {
Requirements::customScript($this->getTrackingScript());
}
}
private function getTrackingScript(): string
{
$data = json_encode($this->getAnalyticsData());
return "window.pageAnalytics = {$data};";
}
}
Elemental Block Tracking
Track SilverStripe Elemental blocks:
<?php
// app/src/Extensions/ElementalAnalyticsExtension.php
namespace App\Extensions;
use SilverStripe\ORM\DataExtension;
class ElementalAnalyticsExtension extends DataExtension
{
public function getBlockAnalyticsData(): array
{
return [
'block_id' => $this->owner->ID,
'block_type' => $this->owner->ClassName,
'block_title' => $this->owner->Title,
'block_position' => $this->owner->Sort,
'parent_page_id' => $this->owner->Parent()?->ID,
];
}
}
<%-- In element template --%>
<section
class="element-{$ClassName.ShortName}"
data-block-id="{$ID}"
data-block-type="{$ClassName.ShortName}"
data-block-position="{$Sort}"
>
$ElementContent
</section>
<script>
// Track block visibility
document.querySelectorAll('[data-block-id]').forEach(block => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
gtag('event', 'block_view', {
block_id: entry.target.dataset.blockId,
block_type: entry.target.dataset.blockType,
block_position: entry.target.dataset.blockPosition
});
observer.unobserve(entry.target);
}
});
}, { threshold: 0.5 });
observer.observe(block);
});
</script>
Form Tracking
Track SilverStripe UserForms submissions:
<?php
// app/src/Extensions/UserFormAnalyticsExtension.php
namespace App\Extensions;
use SilverStripe\ORM\DataExtension;
class UserFormAnalyticsExtension extends DataExtension
{
public function updateAfterProcess($data, $form, $submission)
{
// Add tracking data to response
$trackingData = [
'form_id' => $this->owner->ID,
'form_name' => $this->owner->Title,
'submission_id' => $submission->ID,
];
// This data can be picked up by client-side JavaScript
Requirements::customScript(
"window.formSubmission = " . json_encode($trackingData) . ";"
);
}
}
CMS User Exclusion
Exclude logged-in CMS users from analytics:
<?php
// In AnalyticsPageExtension.php
use SilverStripe\Security\Security;
public function shouldTrack(): bool
{
$member = Security::getCurrentUser();
if ($member && $member->inGroup('administrators')) {
return false;
}
return true;
}
<%-- In template --%>
<% if $shouldTrack %>
<% include Analytics %>
<% end_if %>
Integration Best Practices
1. Use Page IDs for Tracking
SilverStripe pages have stable database IDs:
gtag('event', 'content_view', {
content_id: '{$ID}', // Stable database ID
content_url_segment: '{$URLSegment}', // May change
content_class: '{$ClassName}'
});
2. Track Page Hierarchy
Leverage SilverStripe's page tree:
<%-- Get breadcrumb for tracking --%>
<% cached 'analytics-breadcrumb', $ID, $LastEdited %>
<script>
gtag('event', 'page_view', {
page_id: '{$ID}',
breadcrumb: '<% loop $Breadcrumbs %>{$Title}<% if not $Last %> > <% end_if %><% end_loop %>',
parent_id: '{$ParentID}',
level: {$Level}
});
</script>
<% end_cached %>
3. Handle Versioned Content
Track draft vs. published content:
public function getVersionInfo(): array
{
return [
'is_published' => $this->owner->isPublished(),
'is_modified' => $this->owner->stagesDiffer(),
'version' => $this->owner->Version,
];
}
4. Track Subsites
For SilverStripe Subsites module:
<% with $CurrentSubsite %>
<script>
gtag('set', {
subsite_id: '{$ID}',
subsite_title: '{$Title}',
subsite_domain: '{$getPrimaryDomain}'
});
</script>
<% end_with %>
5. Multi-Language Tracking
For Fluent or similar language modules:
<script>
gtag('event', 'page_view', {
page_id: '{$ID}',
page_locale: '{$CurrentLocale}',
default_locale: '{$DefaultLocale}'
});
</script>
Module Configuration
Installing Analytics Modules
# Install via Composer
composer require silverstripe/google-analytics
# Run dev/build
vendor/bin/sake dev/build flush=1
SiteConfig Extension
<?php
// app/src/Extensions/SiteConfigAnalyticsExtension.php
namespace App\Extensions;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\DataExtension;
class SiteConfigAnalyticsExtension extends DataExtension
{
private static $db = [
'GoogleAnalyticsID' => 'Varchar(50)',
'GTMContainerID' => 'Varchar(50)',
];
public function updateCMSFields(FieldList $fields)
{
$fields->addFieldsToTab('Root.Analytics', [
TextField::create('GoogleAnalyticsID', 'Google Analytics 4 ID')
->setDescription('Format: G-XXXXXXXXXX'),
TextField::create('GTMContainerID', 'GTM Container ID')
->setDescription('Format: GTM-XXXXXXX'),
]);
}
}
Testing Integrations
Template Testing:
- Verify variable output
- Test conditional logic
- Check DataObject access
Module Testing:
- Test dev/build completion
- Verify extension registration
- Check CMS field additions
Elemental Testing:
- Test block type tracking
- Verify block visibility events
- Check nested block handling
Next Steps
Choose your integration to get started:
Additional Resources
SilverStripe Documentation: