react-tag-tracker 0.1.0
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/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +7 -0
- package/dist/jest-setup.d.ts +1 -0
- package/dist/src/TagTrackerContext.d.ts +7 -0
- package/dist/src/TagTrackerProvider.d.ts +3 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/types.d.ts +14 -0
- package/dist/tests/click.test.d.ts +1 -0
- package/dist/tests/hover.test.d.ts +1 -0
- package/dist/tests/main.d.ts +9 -0
- package/dist/tests/render.test.d.ts +1 -0
- package/dist/tests/visbility.test.d.ts +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 José Oscátegui
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# React Tag Tracker for `Google Tag Manager`
|
|
2
|
+
|
|
3
|
+
A lightweight and customizable event tracking library for React that simplifies integration with Google Tag Manager (GTM). It provides tracking for click events, hover interactions and scroll visibility, with the flexibility to customize the tracking attributes and enable/disable features dynamically.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
- **Customizable tracking attribute** (default: `data-track`).
|
|
7
|
+
- **Track click events** on elements with the tracking attribute.
|
|
8
|
+
- **Track hover interactions** (optional).
|
|
9
|
+
- **Track element visibility** when it enters the viewport (optional).
|
|
10
|
+
- **Manual custom event tracking** via the trackCustomEvent method.
|
|
11
|
+
- **Push events directly to Google Tag Manager’s Data Layer**.
|
|
12
|
+
|
|
13
|
+
## 📦 Installation
|
|
14
|
+
You can install the library via npm or yarn:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install react-tag-tracker
|
|
18
|
+
# or
|
|
19
|
+
yarn add react-tag-tracker
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 🎯 Usage
|
|
23
|
+
### 1️⃣ Wrap Your App with TagTrackerProvider
|
|
24
|
+
Wrap your application with the `TagTrackerProvider` and configure the features you want to enable (such as custom attributes, hover tracking, visibility tracking, etc.).
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
import React from 'react';
|
|
28
|
+
import { TagTrackerProvider } from 'react-tag-tracker';
|
|
29
|
+
import App from './App';
|
|
30
|
+
|
|
31
|
+
const Root = () => (
|
|
32
|
+
<TagTrackerProvider
|
|
33
|
+
trackingAttribute="data-custom-track" // Customize the tracking attribute if needed
|
|
34
|
+
enableHoverTracking={true} // Enable hover tracking (optional)
|
|
35
|
+
enableVisibilityTracking={true} // Enable visibility tracking (optional)
|
|
36
|
+
>
|
|
37
|
+
<App />
|
|
38
|
+
</TagTrackerProvider>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export default Root;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 2️⃣ Track Click Events
|
|
45
|
+
You can now track click events on elements with the `data-track` (or your custom attribute) attribute:
|
|
46
|
+
|
|
47
|
+
```jsx
|
|
48
|
+
<button data-track='{"event":"click", "category":"button", "label":"Buy Now"}'>
|
|
49
|
+
Buy Now
|
|
50
|
+
</button>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3️⃣ Track Hover Events (Optional)
|
|
54
|
+
If you’ve enabled `enableHoverTracking`, hover events will be tracked for elements with the tracking attribute:
|
|
55
|
+
|
|
56
|
+
```jsx
|
|
57
|
+
<div data-track='{"event":"hover", "category":"section", "label":"Special Offer"}'>
|
|
58
|
+
Hover over me!
|
|
59
|
+
</div>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4️⃣ Track Visibility Events (Optional)
|
|
63
|
+
If you’ve enabled `enableVisibilityTracking`, the library will track when elements with the tracking attribute enter the viewport:
|
|
64
|
+
|
|
65
|
+
```jsx
|
|
66
|
+
<div data-track='{"event":"visibility", "category":"section", "label":"Featured Product"}'>
|
|
67
|
+
This element is visible when it enters the viewport!
|
|
68
|
+
</div>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 5️⃣ Manually Track Custom Events
|
|
72
|
+
You can also manually push custom events to the GTM Data Layer using the `trackCustomEvent` function from the `useTagTracker` hook:
|
|
73
|
+
|
|
74
|
+
```jsx
|
|
75
|
+
import { useTagTracker } from 'react-tag-tracker';
|
|
76
|
+
|
|
77
|
+
const MyComponent = () => {
|
|
78
|
+
const { trackCustomEvent } = useTagTracker();
|
|
79
|
+
|
|
80
|
+
const handleCustomEvent = () => {
|
|
81
|
+
trackCustomEvent({
|
|
82
|
+
event: 'custom_event',
|
|
83
|
+
action: 'User clicked custom button'
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<button onClick={handleCustomEvent}>
|
|
89
|
+
Track Custom Event
|
|
90
|
+
</button>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 6️⃣ Full Example
|
|
96
|
+
Here’s a complete example:
|
|
97
|
+
|
|
98
|
+
```jsx
|
|
99
|
+
import React from 'react';
|
|
100
|
+
import { TagTrackerProvider, useTagTracker } from 'react-tag-tracker';
|
|
101
|
+
|
|
102
|
+
const App = () => {
|
|
103
|
+
const { trackCustomEvent } = useTagTracker();
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div>
|
|
107
|
+
<button
|
|
108
|
+
data-track='{"event":"click", "category":"button", "label":"Buy Now"}'
|
|
109
|
+
>
|
|
110
|
+
Buy Now
|
|
111
|
+
</button>
|
|
112
|
+
|
|
113
|
+
<div
|
|
114
|
+
data-track='{"event":"hover", "category":"section", "label":"Special Offer"}'
|
|
115
|
+
>
|
|
116
|
+
Hover over me to track hover event!
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div
|
|
120
|
+
data-track='{"event":"visibility", "category":"section", "label":"Featured Product"}'
|
|
121
|
+
>
|
|
122
|
+
I will be tracked when I become visible!
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<button onClick={() => trackCustomEvent({
|
|
126
|
+
event: 'custom_event',
|
|
127
|
+
action: 'User clicked custom button'
|
|
128
|
+
})}>
|
|
129
|
+
Track Custom Event
|
|
130
|
+
</button>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const Root = () => (
|
|
136
|
+
<TagTrackerProvider
|
|
137
|
+
trackingAttribute="data-track"
|
|
138
|
+
enableHoverTracking={true}
|
|
139
|
+
enableVisibilityTracking={true}
|
|
140
|
+
>
|
|
141
|
+
<App />
|
|
142
|
+
</TagTrackerProvider>
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export default Root;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## 🛠️ Configuration Options
|
|
149
|
+
You can configure the following options when using the `TagTrackerProvider`:
|
|
150
|
+
|
|
151
|
+
- **`trackingAttribute`**: The attribute used for event tracking. Default is `data-track`.
|
|
152
|
+
- Example: ```<button data-custom-track='{"event":"click", "category":"button"}'>Click Me</button>```
|
|
153
|
+
|
|
154
|
+
- **`enableHoverTracking`**: Set this to `true` to enable hover event tracking for elements with the tracking attribute. Default is `false`.
|
|
155
|
+
- **`enableVisibilityTracking`**: Set this to `true` to enable visibility tracking for elements with the tracking attribute. Default is false.
|
|
156
|
+
- **`enableCustomTracking`**: Set this to `true` to enable custom event tracking via the trackCustomEvent function. Default is true.
|
|
157
|
+
|
|
158
|
+
## 🎯 Roadmap
|
|
159
|
+
- 🔹 **GA4 Integration**: Send events to Google Analytics 4 (GA4).
|
|
160
|
+
- 🔹 **Event Filters**: Add filtering options to track only specific events.
|
|
161
|
+
|
|
162
|
+
## ✅ Automatic Testing (Jest + Testing Library)
|
|
163
|
+
|
|
164
|
+
| Tag | Description |
|
|
165
|
+
|-----------|------------|
|
|
166
|
+
| 🏷️ [Render] | Check the rendering of the Provider. |
|
|
167
|
+
| 🏷️ [Events] | Test events like `click`, `hover`, `visibility`. |
|
|
168
|
+
| 🏷️ [Custom Attribute] | Check if custom attributes work correctly. |
|
|
169
|
+
| 🏷️ [SSR] | Ensures it works without `window` in SSR. |
|
|
170
|
+
| 🏷️ [Async] | Evaluates events with `setTimeout` or deferred events. |
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## 📜 License
|
|
174
|
+
MIT License. Open to contributions! 🚀
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/TagTrackerProvider.tsx
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
|
|
4
|
+
// src/TagTrackerContext.tsx
|
|
5
|
+
import { createContext, useContext } from "react";
|
|
6
|
+
var TagTrackerContext = createContext(null);
|
|
7
|
+
var useTagTracker = () => {
|
|
8
|
+
const context = useContext(TagTrackerContext);
|
|
9
|
+
if (!context) throw new Error("useTagTracker must be used within a TagTrackerProvider");
|
|
10
|
+
return context;
|
|
11
|
+
};
|
|
12
|
+
var TagTrackerContext_default = TagTrackerContext;
|
|
13
|
+
|
|
14
|
+
// src/TagTrackerProvider.tsx
|
|
15
|
+
import { jsx } from "react/jsx-runtime";
|
|
16
|
+
var TagTrackerProvider = (props) => {
|
|
17
|
+
const {
|
|
18
|
+
children,
|
|
19
|
+
trackingAttribute = "data-track",
|
|
20
|
+
enableHoverTracking = false,
|
|
21
|
+
enableVisibilityTracking = false,
|
|
22
|
+
enableCustomTracking = true
|
|
23
|
+
} = props;
|
|
24
|
+
const handleEvent = (event) => {
|
|
25
|
+
let element = event.target;
|
|
26
|
+
while (element && !element.hasAttribute(trackingAttribute)) {
|
|
27
|
+
element = element.parentElement;
|
|
28
|
+
}
|
|
29
|
+
if (element) {
|
|
30
|
+
const trackData = element.getAttribute(trackingAttribute);
|
|
31
|
+
try {
|
|
32
|
+
const parsedData = JSON.parse(trackData || "{}");
|
|
33
|
+
if (!parsedData.event) throw new Error("Event property is required");
|
|
34
|
+
window.dataLayer = window.dataLayer || [];
|
|
35
|
+
window.dataLayer.push(parsedData);
|
|
36
|
+
console.log("[TagTracker] Event:", parsedData);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.warn("Click event failed:", error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const handleHoverTracking = (event) => {
|
|
43
|
+
if (enableHoverTracking) {
|
|
44
|
+
let element = event.target;
|
|
45
|
+
while (element && !element.hasAttribute(trackingAttribute)) {
|
|
46
|
+
element = element.parentElement;
|
|
47
|
+
}
|
|
48
|
+
if (element) {
|
|
49
|
+
const trackData = element.getAttribute(trackingAttribute);
|
|
50
|
+
try {
|
|
51
|
+
const parsedData = JSON.parse(trackData || "{}");
|
|
52
|
+
parsedData.event = "hover";
|
|
53
|
+
window.dataLayer = window.dataLayer || [];
|
|
54
|
+
window.dataLayer.push(parsedData);
|
|
55
|
+
console.log("[TagTracker] Hover Event:", parsedData);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn("Hover event failed:", error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const handleVisibilityTracking = () => {
|
|
63
|
+
if (enableVisibilityTracking) {
|
|
64
|
+
const elements = document.querySelectorAll(`[${trackingAttribute}]`);
|
|
65
|
+
elements.forEach((element) => {
|
|
66
|
+
const trackData = element.getAttribute(trackingAttribute);
|
|
67
|
+
const rect = element.getBoundingClientRect();
|
|
68
|
+
if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
|
|
69
|
+
try {
|
|
70
|
+
const parsedData = JSON.parse(trackData || "{}");
|
|
71
|
+
parsedData.event = "visibility";
|
|
72
|
+
window.dataLayer = window.dataLayer || [];
|
|
73
|
+
window.dataLayer.push(parsedData);
|
|
74
|
+
console.log("[TagTracker] Visibility Event:", parsedData);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.warn("Visibility tracking failed:", error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const trackCustomEvent = (eventData) => {
|
|
83
|
+
if (enableCustomTracking) {
|
|
84
|
+
if (typeof eventData !== "object") {
|
|
85
|
+
console.warn("trackCustomEvent requires an object parameter");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
window.dataLayer = window.dataLayer || [];
|
|
89
|
+
window.dataLayer.push(eventData);
|
|
90
|
+
console.log("[TagTracker] Custom Event:", eventData);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
document.addEventListener("click", handleEvent);
|
|
95
|
+
if (enableHoverTracking) {
|
|
96
|
+
document.addEventListener("mouseover", handleHoverTracking);
|
|
97
|
+
}
|
|
98
|
+
if (enableVisibilityTracking) {
|
|
99
|
+
window.addEventListener("scroll", handleVisibilityTracking);
|
|
100
|
+
}
|
|
101
|
+
return () => {
|
|
102
|
+
document.removeEventListener("click", handleEvent);
|
|
103
|
+
if (enableHoverTracking) {
|
|
104
|
+
document.removeEventListener("mouseover", handleHoverTracking);
|
|
105
|
+
}
|
|
106
|
+
if (enableVisibilityTracking) {
|
|
107
|
+
window.removeEventListener("scroll", handleVisibilityTracking);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}, [trackingAttribute, enableHoverTracking, enableVisibilityTracking, enableCustomTracking]);
|
|
111
|
+
return /* @__PURE__ */ jsx(TagTrackerContext_default.Provider, { value: { trackCustomEvent }, children });
|
|
112
|
+
};
|
|
113
|
+
var TagTrackerProvider_default = TagTrackerProvider;
|
|
114
|
+
export {
|
|
115
|
+
TagTrackerProvider_default as TagTrackerProvider,
|
|
116
|
+
useTagTracker
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/TagTrackerProvider.tsx", "../src/TagTrackerContext.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useEffect } from 'react';\nimport TagTrackerContext from './TagTrackerContext';\nimport { DataLayerEventProps, TagTrackerProviderProps } from './types';\n\nconst TagTrackerProvider = (props: TagTrackerProviderProps) => {\n const {\n children,\n trackingAttribute = 'data-track',\n enableHoverTracking = false,\n enableVisibilityTracking = false,\n enableCustomTracking = true,\n } = props;\n\n const handleEvent = (event: MouseEvent): void => {\n let element = event.target as HTMLElement;\n\n while (element && !element.hasAttribute(trackingAttribute)) {\n element = element.parentElement as HTMLElement;\n }\n\n if (element) {\n const trackData = element.getAttribute(trackingAttribute);\n\n try {\n const parsedData: DataLayerEventProps = JSON.parse(trackData || '{}');\n if (!parsedData.event) throw new Error('Event property is required');\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(parsedData);\n console.log('[TagTracker] Event:', parsedData);\n } catch (error) {\n console.warn('Click event failed:', error);\n }\n }\n };\n\n const handleHoverTracking = (event: MouseEvent): void => {\n if (enableHoverTracking) {\n let element = event.target as HTMLElement;\n\n while (element && !element.hasAttribute(trackingAttribute)) {\n element = element.parentElement as HTMLElement;\n }\n\n if (element) {\n const trackData = element.getAttribute(trackingAttribute);\n\n try {\n const parsedData: DataLayerEventProps = JSON.parse(trackData || '{}');\n parsedData.event = 'hover';\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(parsedData);\n console.log('[TagTracker] Hover Event:', parsedData);\n } catch (error) {\n console.warn('Hover event failed:', error);\n }\n }\n }\n };\n\n const handleVisibilityTracking = () => {\n if (enableVisibilityTracking) {\n const elements = document.querySelectorAll(`[${trackingAttribute}]`);\n\n elements.forEach((element) => {\n const trackData = element.getAttribute(trackingAttribute);\n const rect = element.getBoundingClientRect();\n\n if (rect.top >= 0 && rect.bottom <= window.innerHeight) {\n try {\n const parsedData = JSON.parse(trackData || '{}');\n parsedData.event = 'visibility';\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(parsedData);\n console.log('[TagTracker] Visibility Event:', parsedData);\n } catch (error) {\n console.warn('Visibility tracking failed:', error);\n }\n }\n });\n }\n };\n\n const trackCustomEvent = (eventData: DataLayerEventProps) => {\n if (enableCustomTracking) {\n if (typeof eventData !== 'object') {\n console.warn('trackCustomEvent requires an object parameter');\n return;\n }\n window.dataLayer = window.dataLayer || [];\n window.dataLayer.push(eventData);\n console.log('[TagTracker] Custom Event:', eventData);\n }\n };\n\n useEffect(() => {\n document.addEventListener('click', handleEvent);\n\n if (enableHoverTracking) {\n document.addEventListener('mouseover', handleHoverTracking);\n }\n\n if (enableVisibilityTracking) {\n window.addEventListener('scroll', handleVisibilityTracking);\n }\n\n return () => {\n document.removeEventListener('click', handleEvent);\n\n if (enableHoverTracking) {\n document.removeEventListener('mouseover', handleHoverTracking);\n }\n\n if (enableVisibilityTracking) {\n window.removeEventListener('scroll', handleVisibilityTracking);\n }\n };\n }, [trackingAttribute, enableHoverTracking, enableVisibilityTracking, enableCustomTracking]);\n\n return (\n <TagTrackerContext.Provider value={{ trackCustomEvent }}>\n { children }\n </TagTrackerContext.Provider>\n );\n};\n\nexport default TagTrackerProvider;\n", "import { createContext, useContext } from 'react';\nimport { DataLayerEventProps } from './types';\n\ninterface TagTrackerContextType {\n trackCustomEvent: (eventData: DataLayerEventProps) => void;\n}\n\nconst TagTrackerContext = createContext<TagTrackerContextType | null>(null);\n\nexport const useTagTracker = () => {\n const context = useContext(TagTrackerContext);\n\n if (!context) throw new Error('useTagTracker must be used within a TagTrackerProvider');\n return context;\n};\n\nexport default TagTrackerContext;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DataLayerEventProps } from './types';
|
|
2
|
+
interface TagTrackerContextType {
|
|
3
|
+
trackCustomEvent: (eventData: DataLayerEventProps) => void;
|
|
4
|
+
}
|
|
5
|
+
declare const TagTrackerContext: import("react").Context<TagTrackerContextType | null>;
|
|
6
|
+
export declare const useTagTracker: () => TagTrackerContextType;
|
|
7
|
+
export default TagTrackerContext;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
type DataPrefixedString = `data-${string}`;
|
|
3
|
+
export interface DataLayerEventProps {
|
|
4
|
+
event: string;
|
|
5
|
+
[key: string]: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TagTrackerProviderProps {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
trackingAttribute?: DataPrefixedString;
|
|
10
|
+
enableHoverTracking?: boolean;
|
|
11
|
+
enableVisibilityTracking?: boolean;
|
|
12
|
+
enableCustomTracking?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { render, RenderOptions } from '@testing-library/react';
|
|
2
|
+
import { TagTrackerProviderProps } from '../src';
|
|
3
|
+
import { ReactElement } from 'react';
|
|
4
|
+
interface CustomRenderOptions extends Omit<RenderOptions, "wrapper"> {
|
|
5
|
+
providerProps?: Partial<TagTrackerProviderProps>;
|
|
6
|
+
}
|
|
7
|
+
declare const customRender: (ui: ReactElement, options?: CustomRenderOptions) => ReturnType<typeof render>;
|
|
8
|
+
export * from "@testing-library/react";
|
|
9
|
+
export { customRender as render };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-tag-tracker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A provider for React that makes it easy to track custom events and automatically send them to window.dataLayer, optimizing integration with tools like GTM.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"registry": "https://registry.npmjs.org/"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"gtm",
|
|
17
|
+
"google-tag-manager",
|
|
18
|
+
"dataLayer",
|
|
19
|
+
"analytics",
|
|
20
|
+
"events",
|
|
21
|
+
"tracking",
|
|
22
|
+
"custom-events",
|
|
23
|
+
"typescript",
|
|
24
|
+
"react-provider",
|
|
25
|
+
"react-hook"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/iLTW1n/react-tag-tracker.git"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@eslint/js": "^9.23.0",
|
|
34
|
+
"@size-limit/preset-small-lib": "^11.2.0",
|
|
35
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
36
|
+
"@testing-library/react": "^16.3.0",
|
|
37
|
+
"@types/jest": "^29.5.14",
|
|
38
|
+
"@types/node": "^22.14.0",
|
|
39
|
+
"@types/react": "^19.1.0",
|
|
40
|
+
"@types/react-dom": "^19.1.1",
|
|
41
|
+
"esbuild": "0.25.2",
|
|
42
|
+
"eslint": "^9.23.0",
|
|
43
|
+
"eslint-plugin-react": "^7.37.4",
|
|
44
|
+
"globals": "^16.0.0",
|
|
45
|
+
"jest": "^29.7.0",
|
|
46
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
47
|
+
"react": "^19.1.0",
|
|
48
|
+
"react-dom": "^19.1.0",
|
|
49
|
+
"size-limit": "^11.2.0",
|
|
50
|
+
"ts-jest": "^29.3.1",
|
|
51
|
+
"typescript": "^5.8.2",
|
|
52
|
+
"typescript-eslint": "^8.29.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"react": "*",
|
|
56
|
+
"react-dom": "*"
|
|
57
|
+
},
|
|
58
|
+
"size-limit": [
|
|
59
|
+
{
|
|
60
|
+
"path": "dist/index.js",
|
|
61
|
+
"limit": "10 KB"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
66
|
+
"build:js": "node esbuild.config.js",
|
|
67
|
+
"build": "pnpm build:types && pnpm build:js",
|
|
68
|
+
"test": "jest",
|
|
69
|
+
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
|
|
70
|
+
"size": "size-limit"
|
|
71
|
+
}
|
|
72
|
+
}
|