Matomo
Overview
Section titled “Overview”The Matomo provider is Agoraform’s first production provider. v0.1.0 introduced analytics goals. v0.2.0 added Matomo Tag Manager variables, triggers, tags, and declarative container publication. v0.5.0 adds matomo.container so a Tag Manager container can be declared and imported instead of requiring a pre-created container id. matomo.tag also supports Matomo’s Google Ads conversion template so a managed Google Ads conversion action can supply conversion ID and label through { $ref, output }.
The Agoraform CLI remains provider-neutral. There is no Matomo-specific publish command.
Source at tag v0.6.0.
Supported capabilities
Section titled “Supported capabilities”matomo.goal— read, create, update, import, removematomo.container— read, create, update, import, destroymatomo.variable— Data Layer and Matomo Configuration variables; read, create, update, import, destroymatomo.trigger— Custom Event triggers; read, create, update, import, destroymatomo.tag— Matomo Analytics event tags and Google Ads conversion tags; read, create, update, import, destroy- Declarative Tag Manager publication through
providers.matomo.publishandproviders.matomo.environment - Logical
$refdependencies and{ $ref, output }selectors with prerequisite-first plan and apply
Agoraform supports two explicit Tag Manager container modes:
- Externally managed container — omit
matomo.containerand setMATOMO_CONTAINER_IDto an existing container, as in v0.2.0. - Agoraform-managed container — declare one
matomo.containerresource and omitMATOMO_CONTAINER_ID. Child Tag Manager resources must reference that container withcontainer: { $ref: matomo.container.* }.
Mixing a managed container with MATOMO_CONTAINER_ID is rejected before mutation. v0.6.0 supports at most one managed Matomo container per manifest.
Prerequisites
Section titled “Prerequisites”- A Matomo instance you are allowed to change
- For goals: a numeric site ID
- For Tag Manager: either a managed
matomo.containeror an existing container selected byMATOMO_CONTAINER_ID - An API token allowed to manage the site/container and, if publishing, to publish to the target environment
Authentication / setup
Section titled “Authentication / setup”Credentials and connection details stay outside the manifest. Set environment variables or use .agoraform.env.
Environment variables
Section titled “Environment variables”MATOMO_URL required Matomo base URL, for example https://matomo.example.comMATOMO_TOKEN_AUTH required API tokenMATOMO_SITE_ID required for managed Matomo site resourcesMATOMO_CONTAINER_ID required for Tag Manager resources/publication when no matomo.container resource is declaredTokens never belong in the manifest, logs, plan output, or local state.
Supported resources
Section titled “Supported resources”matomo.goal
Section titled “matomo.goal”- address: matomo.goal.trial_started attributes: name: Trial Started matchAttribute: event_action pattern: trialStarted| Attribute | Required | Description |
|---|---|---|
name | yes | Goal name; immutable once local state binds the resource |
matchAttribute | yes | Goal matching mode such as event_action, url, or manually |
pattern | unless manually | Value to match |
patternType | no | contains (default), exact, or regex; numeric modes use provider defaults |
Agoraform preserves unmanaged Goal fields during updates. Provider-native goal IDs are stored in local state. Manifests that still contain idGoal are rejected. Destroy plans goals as a provider-native remove.
matomo.container
Section titled “matomo.container”- address: matomo.container.main attributes: name: Main Website context: web description: primary web container| Attribute | Required | Notes |
|---|---|---|
name | yes | Container display name |
context | yes | web, android, or ios. Immutable after create |
description | no | Optional description |
Provider-native container IDs, draft version IDs, publication state, and unmanaged Matomo flags such as ignoreGtmDataLayer remain computed. Agoraform preserves those flags on update.
Container deletion is implemented by agoraform destroy for containers that are present in the manifest and bound in local state. Containers selected only by MATOMO_CONTAINER_ID are never deleted.
agoraform import matomo.container.main CONTAINER_IDmatomo.variable
Section titled “matomo.variable”- address: matomo.variable.user_id attributes: container: $ref: matomo.container.main type: dataLayer key: userId name: User ID
- address: matomo.variable.config attributes: container: $ref: matomo.container.main type: matomoConfiguration name: Matomo Configuration matomoUrl: https://matomo.example.com siteId: 1 enableLinkTracking: trueIn external-container mode omit container and set MATOMO_CONTAINER_ID.
type | Required fields | Notes |
|---|---|---|
dataLayer | key | name optional; defaults to key |
matomoConfiguration | name, matomoUrl, siteId | enableLinkTracking optional boolean |
type is immutable after the resource is bound. matomoConfiguration manages a stable initial subset: Matomo URL, site ID, and optional link tracking. Cookie, consent, domain, cross-domain, and custom dimension settings are unowned. Updates read the complete remote variable and round-trip every unowned template parameter unchanged.
Agoraform may encounter other, unmanaged Matomo variable types while reading a container. Their scalar and structured parameter values are tolerated so they do not prevent managed variables from being planned or applied. v0.2.1 fixed structured Matomo variable parameter decoding; that fix is present in v0.6.0.
matomo.trigger
Section titled “matomo.trigger”- address: matomo.trigger.trial_started attributes: container: $ref: matomo.container.main type: customEvent event: trialStartedtype: customEvent and event are required. name is optional and defaults to event. container follows the same managed-versus-external rule as variables. Updates preserve unmanaged description/conditions.
matomo.tag
Section titled “matomo.tag”- address: matomo.tag.trial_started attributes: container: $ref: matomo.container.main type: matomoAnalytics trigger: $ref: matomo.trigger.trial_started eventCategory: signup eventAction: trialStarted matomoConfiguration: $ref: matomo.variable.config
- address: matomo.tag.google_ads_trial_started attributes: container: $ref: matomo.container.main type: googleAdsConversion name: Google Ads trial started trigger: $ref: matomo.trigger.trial_started conversionId: $ref: googleads.conversion_action.trial_started output: conversionId conversionLabel: $ref: googleads.conversion_action.trial_started output: conversionLabelMatomo Analytics tags need a Matomo Configuration variable. Fully managed setups declare type: matomoConfiguration and reference it from the tag. Existing containers can keep using a single pre-existing configuration variable: omit matomoConfiguration and Agoraform locates it in the target container. If several configuration variables exist and none is named Matomo Configuration, implicit discovery fails until you add an explicit $ref or keep a single configuration variable.
Supported fields for type: matomoAnalytics:
| Attribute | Required | Notes |
|---|---|---|
type | yes | matomoAnalytics or googleAdsConversion. Immutable after create |
trigger | yes | $ref to managed matomo.trigger |
eventCategory | yes for matomoAnalytics | Literal or supported variable $ref |
eventAction | yes for matomoAnalytics | Literal or supported variable $ref |
eventName | no | Literal or supported variable $ref |
eventValue | no | Numeric literal/string or supported variable $ref |
name | no | Defaults from eventAction when possible |
container | managed mode | $ref to the declared matomo.container |
matomoConfiguration | no | $ref to a managed matomo.variable with type matomoConfiguration |
Supported fields for type: googleAdsConversion:
| Attribute | Required | Notes |
|---|---|---|
conversionId | yes | Literal, Matomo variable $ref, or { $ref, output: conversionId } from googleads.conversion_action |
conversionLabel | yes | Literal, Matomo variable $ref, or { $ref, output: conversionLabel } from googleads.conversion_action |
conversionValue | no | Optional template value. Omitted values are not forced onto the remote tag |
conversionCurrency | no | Optional currency code |
conversionTransactionId | no | Optional order/transaction id |
Google Ads conversion tags do not use a Matomo Configuration variable. Equivalent conversion IDs such as 9988776655 and AW-9988776655 compare equal. Unmanaged template parameters and omitted optional fields are preserved on update.
Agoraform configures the Matomo tag and can consume outputs from a managed Google Ads conversion action. It does not emit the application event. The Google Ads conversion tag also depends on a Google Tag (gtag.js) in the same container; Agoraform does not manage that Google Tag resource.
Import reconstructs logical trigger/variable $refs when related remote objects are already in local state. For a Google Ads conversion tag, import reconstructs { $ref, output } only when a bound googleads.conversion_action uniquely matches. Ambiguous and absent matches emit literals. Import never guesses a relationship.
Example manifest
Section titled “Example manifest”See the quick start and the tagged Matomo + Google Ads lifecycle example. The earlier conversion example remains valid for the external MATOMO_CONTAINER_ID path.
Publication
Section titled “Publication”providers: matomo: publish: true environment: livepublish defaults to false. environment defaults to live when publication is enabled. Omitting providers.matomo leaves publication disabled.
When publication is required, plan shows:
> matomo.container.main: publish -> live [conditional]With MATOMO_CONTAINER_ID and no matomo.container resource, that action is addressed as matomo.container.external.
apply and destroy first reconcile all planned draft resources. Only after those mutations succeed do they recheck the converged draft, create a container version if needed, and publish it to the configured environment. When a destroy plan will delete the managed container, destroy does not publish an intermediate version.
Before version creation, Agoraform verifies that the credentials can publish to the configured environment using TagManager.getAvailableEnvironmentsWithPublishCapability. Unknown environments or insufficient publish capability fail before the version-creation mutation.
Publication comparison ignores provider-native IDs and computed version metadata. Behavioral tag status (active versus paused) is part of the comparison.
An empty, JSON null, unreadable, oversized, or otherwise unrecognizable publish response is not treated as success.
Known limitations
Section titled “Known limitations”- One Matomo Tag Manager container at a time, either by
matomo.containerorMATOMO_CONTAINER_ID - Tag Manager types are limited to containers, Data Layer and Matomo Configuration variables, Custom Event triggers, Matomo Analytics event tags, and Google Ads conversion tags
- Agoraform does not emit application events or manage Google Tag (
gtag.js) - No provider-specific
agoraform publishcommand - Rollback, scheduled publication, approval workflows, and multi-container orchestration are not implemented
- Containers selected only by
MATOMO_CONTAINER_IDare never deleted applydoes not delete remote resources; useagoraform destroy