Mapping Page Data: Worked Examples
This guide is part of Mapping Page Data into Toggl.
📐 Three complete mappings, all verified against live pages. Copy one into the side-panel editor as a starting point.
Jira — one extra tag
The smallest useful change: take the shipped Jira integration and add the issue's status as a field:value tag.
Add to resolvers:
"statusTag": {
"root": true,
"query": "[data-testid=\"issue-field-status.ui.status-view.status-button.status-button--text\"]",
"regex": "^(.*)$",
"replace": "Status:$1"
}
Add to the button, beside project:
"tags": ["statusTag"]
Result: task SCRUM-3 Test 2, project My Software Team, tag Status:To Do.
GitHub — project from the URL, five tags
Shows values coming from two sources at once: the page and the URL.
Add to resolvers:
"repoProject": { "url": "path", "regex": "^/([^/]+/[^/]+)", "replace": "$1" },
"labelTag": {
"closest": "@issue-viewer",
"query": "div[data-testid=\"issue-labels\"] span[class^=\"prc-Text-Text\"]",
"regex": "^(.*)$",
"replace": "Label:$1"
},
"stateTag": {
"closest": "@issue-viewer",
"query": "[data-testid=\"header-state\"]",
"regex": "^(.*)$",
"replace": "State:$1"
},
"authorTag": {
"closest": "@issue-viewer",
"query": "[data-testid=\"issue-body-header-author\"]",
"regex": "^(.*)$",
"replace": "Author:$1"
},
"orgTag": { "url": "path", "regex": "^/([^/]+)/", "replace": "Org:$1" },
"kindTag": { "url": "path", "regex": "/issues/", "replace": "Kind:Issue" }
On the issues button:
"project": ["repoProject"],
"tags": ["labelTag", "stateTag", "authorTag", "orgTag", "kindTag"]
Result: project vitejs/vite, plus Label:pending triage, State:Open, Author:hermandsen, Org:vitejs, Kind:Issue.
Why it matters commercially: time on any issue in a repository rolls up to that repository automatically. Nobody creates the project, nobody remembers to pick it.
Zendesk — project per customer
The same idea aimed at support, where the useful grouping is the customer.
Add to resolvers (PANE below is .ticket-panes-grid-layout, the wrapper around one open ticket):
"requesterProject": {
"closest": ".ticket-panes-grid-layout",
"query": "[data-test-id=\"ticket-system-field-requester-select\"]",
"regex": "^(.*)$",
"replace": "Support · $1"
},
"priorityTag": {
"closest": ".ticket-panes-grid-layout",
"query": "[data-test-id=\"ticket-fields-priority-select\"]",
"regex": "^(.*)$",
"replace": "Priority:$1"
},
"agentTag": {
"closest": ".ticket-panes-grid-layout",
"query": "[data-test-id=\"assignee-field-selected-agent-tag\"]",
"regex": "^.*/(.*)$",
"replace": "Agent:$1"
},
"channelTag": {
"closest": ".ticket-panes-grid-layout",
"query": "[data-test-id=\"omni-header-via-label\"]",
"regex": "^Via (.*)$",
"replace": "Channel:$1"
},
"zdTag": {
"closest": ".ticket-panes-grid-layout",
"query": "[data-test-id=\"ticket-system-field-tags-item-selected\"] span.garden-tag-item",
"regex": "^(.*)$",
"replace": "Zendesk:$1"
},
"ticketTag": {
"closest": ".ticket-panes-grid-layout",
"textAttribute": "data-test-id",
"regex": "ticket-([0-9]+)-",
"replace": "Ticket:#$1"
}
On the button:
"project": ["requesterProject"],
"tags": ["priorityTag", "agentTag", "channelTag", "zdTag", "ticketTag"]
Result: project Support · Customer, plus Priority:Normal, Agent:Sanjin Kapetanovich, Channel:email, Zendesk:zendesk_accelerated_setup, Ticket:#1.
Three of these show off the format beyond a simple prefix: Agent: throws away the group prefix with a capture group, Channel: strips the word "Via", and Ticket: reads an HTML attribute rather than any visible text.
Every resolver here is scoped with closest to the ticket pane rather than root, because Zendesk keeps several tickets open at once as tabs. root would let a button read a different ticket's fields.
One left undone
Zendesk's ticket status is not mapped above. Zendesk renders it as status-badge-open, with the value baked into the attribute name rather than the text, and the element sits outside the ticket pane. With several tickets open it cannot be safely scoped. Doable, but it needs testing with multiple tabs open before it belongs in a customer-facing setup.