@analitikisler/ai-tag-debugger 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/browser.js +14 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.5 (2026-10-14)
|
|
4
|
+
|
|
5
|
+
- A saved click keeps the element's text as well as its path through the page. When a replay finds nothing visible at that path (a banner or overlay shifted the layout), it clicks the element with that text instead. Sites saved before 0.7.5 have no text to fall back on; save them again to use it.
|
|
6
|
+
|
|
3
7
|
## 0.7.4 (2026-10-14)
|
|
4
8
|
|
|
5
9
|
- Saving a site no longer fails on pages that keep a request open after they are left (a GA4 hit to `www.google.com/g/collect`, for example). The recording waited for it until the 30-second limit and was then skipped, so the site was not saved. The browser's pages are now closed before the recording is written.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analitikisler/ai-tag-debugger",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Open-source AI agent that QA-tests your website's analytics, ad and consent tracking (GA4, GTM, Google Ads, Meta, TikTok). Bring your own model (Claude, OpenAI, Gemini) or use it from your chat app over MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/browser.js
CHANGED
|
@@ -202,7 +202,7 @@ function trackingBody(request) {
|
|
|
202
202
|
* else a CSS path to the element, else its visible text. Refs only mean something in one run.
|
|
203
203
|
*/
|
|
204
204
|
async function replayTarget(a, locator) {
|
|
205
|
-
if (a.selector) return { selector: a.selector };
|
|
205
|
+
if (a.selector) return { selector: a.selector, ...(a.text ? { text: a.text } : {}) };
|
|
206
206
|
const found = await locator
|
|
207
207
|
.evaluate((el) => {
|
|
208
208
|
const text = (el.innerText || el.value || el.getAttribute("aria-label") || "").replace(/\s+/g, " ").trim().slice(0, 80);
|
|
@@ -220,8 +220,10 @@ async function replayTarget(a, locator) {
|
|
|
220
220
|
return { selector: parts.join(" > "), text };
|
|
221
221
|
}, null, { timeout: 5000 })
|
|
222
222
|
.catch(() => null);
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
const text = found?.text || a.text;
|
|
224
|
+
// The text too, since a path through the page's layout breaks when a banner or overlay shifts it.
|
|
225
|
+
if (found?.selector) return { selector: found.selector, ...(text ? { text } : {}) };
|
|
226
|
+
return text ? { text } : {};
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
// Images, fonts and video don't change what tracking sends, and are most of a recording's size.
|
|
@@ -739,7 +741,15 @@ export class AuditSession {
|
|
|
739
741
|
case "fill":
|
|
740
742
|
case "select": {
|
|
741
743
|
let target;
|
|
742
|
-
if (a.selector
|
|
744
|
+
if (a.selector && typeof a.text === "string" && a.text.trim()) {
|
|
745
|
+
// A saved step: its path first, then its text if the path finds nothing to click.
|
|
746
|
+
target = this.locatorFor(a);
|
|
747
|
+
const shown = await target.waitFor({ state: "visible", timeout: 5000 }).then(() => true, () => false);
|
|
748
|
+
if (!shown) {
|
|
749
|
+
const found = await this.locateByText(a.text.trim());
|
|
750
|
+
if (!found.error) target = found.locator;
|
|
751
|
+
}
|
|
752
|
+
} else if (a.selector || Number.isInteger(a.ref)) target = this.locatorFor(a);
|
|
743
753
|
else if (typeof a.text === "string" && a.text.trim()) {
|
|
744
754
|
const found = await this.locateByText(a.text.trim());
|
|
745
755
|
if (found.error) return found.error;
|