Turned the analytics tracker off by default in the template.
This commit is contained in:
@@ -49,6 +49,7 @@ func application(
|
||||
router: router(
|
||||
staticFilesPath: reader.staticFilesPath,
|
||||
assetVersion: fingerprintAssets(reader.staticFilesPath),
|
||||
analytics: reader.analytics,
|
||||
cacheControl: reader.cacheControl,
|
||||
compressionMinResponseSize: reader.compressionMinResponseSize,
|
||||
rateLimit: reader.rateLimit,
|
||||
@@ -145,9 +146,10 @@ private func logger(
|
||||
/// - Parameters:
|
||||
/// - staticFilesPath: the folder, relative to the working directory, the static files are served from.
|
||||
/// - assetVersion: the version token the pages append to their asset URLs, or `nil` to leave them unversioned.
|
||||
/// - analytics: the analytics tracker both pages embed, or `nil` to omit it.
|
||||
/// - cacheControl: the cache-control directives applied to the served static files.
|
||||
/// - compressionMinResponseSize: the minimum response body size, in bytes, before compression is applied.
|
||||
/// - rateLimit: the rate limit applied to the subscription endpoint.
|
||||
/// - rateLimit: the rate limit applied to the rate-limited routes.
|
||||
/// - securityHeaders: the security headers applied to every response.
|
||||
/// - logLevel: the level the request-logging middleware logs at.
|
||||
/// - probe: the probe consulted by the `HealthController` readiness route.
|
||||
@@ -155,6 +157,7 @@ private func logger(
|
||||
private func router(
|
||||
staticFilesPath: String,
|
||||
assetVersion: String?,
|
||||
analytics: Analytics?,
|
||||
cacheControl: CacheControl,
|
||||
compressionMinResponseSize: Int,
|
||||
rateLimit: RateLimitMiddleware<AppRequestContext>.Configuration,
|
||||
@@ -180,7 +183,8 @@ private func router(
|
||||
)
|
||||
LocalizationMiddleware()
|
||||
NotFoundMiddleware(
|
||||
assetVersion: assetVersion
|
||||
assetVersion: assetVersion,
|
||||
analytics: analytics
|
||||
)
|
||||
FileMiddleware(
|
||||
staticFilesPath,
|
||||
@@ -190,7 +194,8 @@ private func router(
|
||||
|
||||
router.addController {
|
||||
RootController<AppRequestContext>(
|
||||
assetVersion: assetVersion
|
||||
assetVersion: assetVersion,
|
||||
analytics: analytics
|
||||
)
|
||||
HealthController<AppRequestContext>(
|
||||
probe: probe
|
||||
|
||||
@@ -14,19 +14,21 @@ package extension ConfigReader {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
/// The analytics tracker the landing page embeds, built from the `analytics.*` keys, or `nil` when `analytics.websiteID` resolves
|
||||
/// empty — a deployment disables analytics entirely by clearing the identifier.
|
||||
/// The analytics tracker both pages embed, built from the `analytics.*` keys, or `nil` when `analytics.websiteID` resolves empty.
|
||||
///
|
||||
/// The identifier is empty by default, so the template serves no tracker at all until a deployment sets `analytics.websiteID` — and
|
||||
/// clearing it again disables analytics entirely.
|
||||
///
|
||||
/// The script URL is not configurable: its origin is single-sourced in `String.Analytics`, so the tracker tag and the
|
||||
/// `Content-Security-Policy` that must allow it derive from one constant and cannot drift apart.
|
||||
/// `Content-Security-Policy` that must allow it derive from one constant and cannot drift apart. Point that constant at your own
|
||||
/// instance, and extend `security.contentSecurityPolicy` to allow it, before enabling analytics.
|
||||
///
|
||||
/// The `analytics.domains` filter must name the host the pages are served from — i.e. the host of ``siteOrigin``. The two keys are
|
||||
/// independent, so a deployment that overrides `site.origin` without matching `analytics.domains` reports from a host it no longer
|
||||
/// serves and records nothing; change them together.
|
||||
/// The `analytics.domains` filter must name the host the pages are served from; it is empty by default, which reports from every host.
|
||||
/// Set it to a host the deployment does not serve and the tracker silently records nothing.
|
||||
///
|
||||
/// Recorder mode is on by default — the pages embed the session recorder script alongside the tracker — and the `analytics.recorder`
|
||||
/// flag turns it off for a deployment. The recorder loads from the same origin as the tracker, so the `Content-Security-Policy` needs
|
||||
/// no extra allowance.
|
||||
/// Recorder mode is off by default — session recording is the most invasive thing the tracker does, so a deployment opts into it
|
||||
/// deliberately with the `analytics.recorder` flag. When on, the pages embed the session recorder script alongside the tracker; it loads
|
||||
/// from the same origin, so the `Content-Security-Policy` needs no extra allowance.
|
||||
var analytics: Analytics? {
|
||||
let websiteID = string(
|
||||
forKey: .Analytics.websiteID,
|
||||
@@ -46,7 +48,7 @@ package extension ConfigReader {
|
||||
),
|
||||
recorder: bool(
|
||||
forKey: .Analytics.recorder,
|
||||
default: true
|
||||
default: false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ struct IndexPage {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The analytics tracker embedded as a deferred script in the document head, or `nil` to omit it.
|
||||
let analytics: Analytics?
|
||||
|
||||
/// The version token appended to the page's asset URLs, or `nil` to leave them unversioned.
|
||||
let assetVersion: String?
|
||||
|
||||
@@ -23,10 +26,13 @@ struct IndexPage {
|
||||
/// - Parameters:
|
||||
/// - locale: the locale the page content is localized to.
|
||||
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
|
||||
/// - analytics: the analytics tracker embedded in the document head, or `nil` (the default) to omit it.
|
||||
init(
|
||||
locale: Locale,
|
||||
assetVersion: String? = nil
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
) {
|
||||
self.analytics = analytics
|
||||
self.assetVersion = assetVersion
|
||||
self.locale = locale
|
||||
self.localize = .init(bundle: .module)
|
||||
|
||||
@@ -8,6 +8,9 @@ struct NotFoundPage {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The analytics tracker embedded as a deferred script in the document head, or `nil` to omit it.
|
||||
let analytics: Analytics?
|
||||
|
||||
/// The version token appended to the page's asset URLs, or `nil` to leave them unversioned.
|
||||
let assetVersion: String?
|
||||
|
||||
@@ -24,10 +27,13 @@ struct NotFoundPage {
|
||||
/// - locale: the locale the page content is localized to.
|
||||
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the
|
||||
/// default) to leave them unversioned.
|
||||
/// - analytics: the analytics tracker embedded in the document head, or `nil` (the default) to omit it.
|
||||
init(
|
||||
locale: Locale,
|
||||
assetVersion: String? = nil
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
) {
|
||||
self.analytics = analytics
|
||||
self.assetVersion = assetVersion
|
||||
self.locale = locale
|
||||
self.localize = .init(bundle: .module)
|
||||
|
||||
@@ -23,14 +23,18 @@ public struct RootController<Context: LocalizedRequestContext> {
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a root controller.
|
||||
/// - Parameter assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
|
||||
/// - Parameters:
|
||||
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
|
||||
/// - analytics: the analytics tracker the landing page embeds, or `nil` (the default) to omit it.
|
||||
public init(
|
||||
assetVersion: String? = nil
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
) {
|
||||
self.responses = .init(bundle: .module) {
|
||||
IndexPage(
|
||||
locale: $0,
|
||||
assetVersion: assetVersion
|
||||
assetVersion: assetVersion,
|
||||
analytics: analytics
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -6,14 +6,18 @@ public extension NotFoundMiddleware {
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a not-found middleware that renders the website's error page, localized to the module's String Catalog languages.
|
||||
/// - Parameter assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
|
||||
/// - Parameters:
|
||||
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
|
||||
/// - analytics: the analytics tracker the error page embeds, or `nil` (the default) to omit it.
|
||||
init(
|
||||
assetVersion: String? = nil
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
) {
|
||||
self.init(bundle: .module) {
|
||||
NotFoundPage(
|
||||
locale: $0,
|
||||
assetVersion: assetVersion
|
||||
assetVersion: assetVersion,
|
||||
analytics: analytics
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
extension String {
|
||||
/// A namespace for the analytics default configuration values.
|
||||
///
|
||||
/// Analytics ships **off**: ``websiteID`` is empty, so the pages embed no tracker until a deployment sets `analytics.websiteID`. Point
|
||||
/// ``origin`` at your own instance before enabling it — the placeholder is an [RFC 2606](https://www.rfc-editor.org/rfc/rfc2606)
|
||||
/// reserved domain, so an unconfigured copy can never report to someone else's server.
|
||||
public enum Analytics {
|
||||
/// The origin the analytics scripts are loaded from and their beacons are sent to (scheme and host, no trailing slash).
|
||||
///
|
||||
/// Single-sourced here: both ``scriptURL`` and the session recorder script the pages embed in recorder mode derive from this
|
||||
/// constant, and the site's `Content-Security-Policy` must allow it.
|
||||
public static let origin = "https://analytics.rock-n-code.com"
|
||||
/// constant. It is deliberately not a configuration key — the `Content-Security-Policy` must allow the same origin, and a value that
|
||||
/// can drift at runtime would silently break the tracker it is supposed to permit.
|
||||
public static let origin = "https://analytics.example.com"
|
||||
/// The URL the analytics tracker script is loaded from.
|
||||
public static let scriptURL = "\(origin)/script"
|
||||
/// The default analytics website identifier the tracker reports as.
|
||||
public static let websiteID = "f28681d6-20e8-43f3-9c3b-5d6a0f8e0591"
|
||||
/// The default comma-delimited domains the tracker reports from; visits from any other host are ignored.
|
||||
/// The default analytics website identifier the tracker reports as: empty, which omits the tracker entirely.
|
||||
public static let websiteID = ""
|
||||
/// The default comma-delimited domains the tracker reports from: empty, which reports from every host.
|
||||
///
|
||||
/// Keep it paired with the host the pages are served at: a deployment that serves from another host without overriding
|
||||
/// `analytics.domains` to match reports from a host it no longer serves, so analytics silently records nothing.
|
||||
public static let domains = "loud.amsterdam"
|
||||
/// Once set, keep it paired with the host the pages are served at — a deployment that serves from another host without matching
|
||||
/// `analytics.domains` reports from a host it no longer serves, so analytics silently records nothing.
|
||||
public static let domains = ""
|
||||
}
|
||||
/// A namespace for the persistence's default configuration values and recognized tokens.
|
||||
public enum Database {
|
||||
|
||||
Reference in New Issue
Block a user