| name | tag_manager |
| description | Manage Matomo Tag Manager triggers, tags, and deployments with POST operations and validation |
Matomo Tag Manager Skill
When to Use This Skill
Use this skill when you need to:
- Create triggers (click tracking, page views, form submissions)
- Create tags (custom HTML, Matomo events, third-party integrations)
- Deploy tags to environments (live, staging, dev)
- Add Tally feedback forms or other popups
- Test changes with preview mode before publishing
- Manage Tag Manager workflow (draft → test → publish → cleanup)
Prerequisites
Before using Tag Manager operations:
- Know your site ID and container ID - Check
knowledge/sites/ for site details
- Read tag-manager.md -
knowledge/matomo/tag-manager.md for concepts
- Understand draft vs live - Draft IDs ≠ Published IDs (they change on publish)
Core Workflow
All Tag Manager operations use lib.query:
from lib.query import get_matomo
api = get_matomo("inclusion")
Complete Example: Click Tracking
from lib.query import get_matomo
api = get_matomo("inclusion")
draft_id = api.get_draft_version(site_id=210, container_id="xg8aydM9")
trigger_id = api.add_trigger(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
trigger_type="AllElementsClick",
name="Button clicks",
conditions=[
{"comparison": "contains", "actual": "ClickClasses", "expected": "btn-primary"}
]
)
tag_id = api.add_tag(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
tag_type="CustomHtml",
name="Log clicks",
parameters={
"customHtml": "<script>console.log('clicked!');</script>",
"htmlPosition": "bodyEnd"
},
fire_trigger_ids=[trigger_id],
fire_limit="once_page"
)
api.enable_preview(site_id=210, container_id="xg8aydM9")
api.publish_version(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
environment="live"
)
api.disable_preview(site_id=210, container_id="xg8aydM9")
Common Pattern: Tally Form Popup
Trigger a Tally feedback form when users view a specific page (bottom-right popup).
from lib.query import get_matomo
api = get_matomo("inclusion")
draft_id = api.get_draft_version(site_id=210, container_id="xg8aydM9")
trigger_id = api.add_trigger(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
trigger_type="PageView",
name="XP BENEF - Vue d'une page Service",
conditions=[
{"comparison": "starts_with", "actual": "PageUrl",
"expected": "https://dora-staging.inclusion.beta.gouv.fr/services/"}
]
)
tag_id = api.add_tag(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
tag_type="CustomHtml",
name="XP - appel tag Tally",
parameters={
"customHtml": """<script>
(function(d,t) {
var s=d.createElement(t),options={'formId':'YOUR_FORM_ID','popup':{'open':{'trigger':'time','ms':2000},'layout':'default','autoClose':30000}};
s.src='https://tally.so/widgets/embed.js';
s.onload=function(){Tally.loadEmbeds(options);};
d.head.appendChild(s);
})(document,'script');
</script>""",
"htmlPosition": "bodyEnd"
},
fire_trigger_ids=[trigger_id],
fire_limit="once_24hours",
status="active"
)
api.enable_preview(site_id=210, container_id="xg8aydM9")
api.publish_version(
site_id=210,
container_id="xg8aydM9",
version_id=draft_id,
environment="live"
)
Key parameters explained:
trigger_type="PageView" — fires when page loads
conditions with starts_with — matches all service detail pages
fire_limit="once_24hours" — prevents popup spam
- Tally's
popup config controls timing and position
Gotchas
1. Draft vs Published IDs Change
When you publish, Matomo creates a new version and assigns new IDs to all objects:
draft (v420) publication v972 (live)
trigger 13994 ──────────────────────────→ trigger 14030
tag 11149 ──────────────────────────→ tag 11170
Keep draft IDs if you need to update/delete later in the draft.
2. Delete from Both Draft and Live
Deleting from draft doesn't remove from published versions. To fully remove:
api.delete_trigger(site_id=210, container_id="xg8aydM9", version_id=DRAFT_ID, trigger_id=DRAFT_TRIGGER_ID)
api.delete_trigger(site_id=210, container_id="xg8aydM9", version_id=LIVE_VERSION, trigger_id=LIVE_TRIGGER_ID)
api.publish_version(site_id=210, container_id="xg8aydM9", version_id=DRAFT_ID, environment="live")
3. Preview Mode Uses Cookies
enable_preview() sets a cookie in your browser. The site loads the draft version when the cookie is present. Clear cookies or use disable_preview() to return to live.
Available Methods
Container Operations
container = api.get_container(site_id=210, container_id="xg8aydM9")
draft_id = api.get_draft_version(site_id=210, container_id="xg8aydM9")
Trigger Operations
trigger_id = api.add_trigger(
site_id, container_id, version_id,
trigger_type="PageView",
name="My Trigger",
conditions=[{"comparison": "equals", "actual": "PageUrl", "expected": "/test"}]
)
api.update_trigger(site_id, container_id, version_id, trigger_id, name="New Name")
api.delete_trigger(site_id, container_id, version_id, trigger_id)
Valid trigger types: AllElementsClick, AllLinksClick, PageView, FormSubmit, HistoryChange, WindowLoaded, ElementVisibility, CustomEvent
Condition operators: equals, contains, starts_with, ends_with, matches_regex, etc.
Tag Operations
tag_id = api.add_tag(
site_id, container_id, version_id,
tag_type="CustomHtml",
name="My Tag",
parameters={"customHtml": "<script>...</script>", "htmlPosition": "bodyEnd"},
fire_trigger_ids=[trigger_id],
fire_limit="unlimited",
status="active",
priority=999
)
api.update_tag(site_id, container_id, version_id, tag_id, name="New Name")
api.delete_tag(site_id, container_id, version_id, tag_id)
api.pause_tag(site_id, container_id, version_id, tag_id)
api.resume_tag(site_id, container_id, version_id, tag_id)
Valid tag types: CustomHtml, Matomo, LinkedinInsight
Valid fire limits: unlimited, once_page, once_24hours, once_lifetime
Valid HTML positions: headStart, headEnd, bodyStart, bodyEnd
Workflow Operations
api.publish_version(
site_id, container_id, version_id,
environment="live"
)
api.enable_preview(site_id, container_id)
api.disable_preview(site_id, container_id)
data = api.export_version(site_id, container_id, version_id)
print(f"Triggers: {len(data['triggers'])}, Tags: {len(data['tags'])}")
Valid environments: live, staging, dev, production, pentest, preview
Validation
All helper methods validate parameters before making API calls:
- trigger_type must be in
VALID_TRIGGER_TYPES
- tag_type must be in
VALID_TAG_TYPES
- fire_limit must be in
VALID_FIRE_LIMITS
- environment must be in
VALID_ENVIRONMENTS
Invalid values raise ValueError with clear error messages listing valid options.
Generic POST for Advanced Use
For Tag Manager operations not covered by helpers, use the generic post() method:
result = api.post(
"TagManager.addContainerVariable",
idSite=210,
idContainer="xg8aydM9",
idContainerVersion=420,
type="DataLayer",
name="myVariable",
parameters={"dataLayerName": "customData"}
)
Python dicts/lists are automatically flattened to PHP array notation.
Reference