@jwiedeman/gtm-kit-react-legacy 1.1.2 → 1.1.4
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/README.md +187 -86
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @jwiedeman/gtm-kit-react-legacy
|
|
2
2
|
|
|
3
|
-
[](https://github.com/jwiedeman/GTM-Kit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/jwiedeman/GTM-Kit)
|
|
5
|
+
[](https://www.npmjs.com/package/@jwiedeman/gtm-kit-react-legacy)
|
|
6
|
+
[](https://bundlephobia.com/package/@jwiedeman/gtm-kit-react-legacy)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
[](https://reactjs.org/)
|
|
@@ -17,38 +17,39 @@ The legacy React adapter for GTM Kit - uses HOC pattern for class component comp
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install @
|
|
20
|
+
npm install @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
yarn add @
|
|
24
|
+
yarn add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
pnpm add @
|
|
28
|
+
pnpm add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
## When to Use This Package
|
|
34
34
|
|
|
35
|
-
Use `@
|
|
35
|
+
Use `@jwiedeman/gtm-kit-react-legacy` if:
|
|
36
36
|
|
|
37
37
|
- You're using class components
|
|
38
38
|
- Your project uses React < 16.8 (no hooks)
|
|
39
39
|
- You prefer the HOC pattern
|
|
40
40
|
- You're maintaining a legacy codebase
|
|
41
41
|
|
|
42
|
-
**For new projects**, we recommend [`@
|
|
42
|
+
**For new projects**, we recommend [`@jwiedeman/gtm-kit-react`](https://www.npmjs.com/package/@jwiedeman/gtm-kit-react) which uses hooks.
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
46
46
|
## Quick Start
|
|
47
47
|
|
|
48
|
-
### Step 1: Wrap Your
|
|
48
|
+
### Step 1: Wrap Your Root Component
|
|
49
49
|
|
|
50
50
|
```tsx
|
|
51
|
-
import
|
|
51
|
+
import React from 'react';
|
|
52
|
+
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';
|
|
52
53
|
|
|
53
54
|
class App extends React.Component {
|
|
54
55
|
render() {
|
|
@@ -56,17 +57,22 @@ class App extends React.Component {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
// Wrap with GTM - note the curried function pattern
|
|
61
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(App);
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
### Step 2:
|
|
64
|
+
### Step 2: Use the GTM API in Child Components
|
|
65
|
+
|
|
66
|
+
The `withGtm` HOC injects a `gtm` prop with the full GTM API:
|
|
63
67
|
|
|
64
68
|
```tsx
|
|
65
|
-
import
|
|
69
|
+
import React from 'react';
|
|
70
|
+
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';
|
|
66
71
|
|
|
67
72
|
class BuyButton extends React.Component {
|
|
68
73
|
handleClick = () => {
|
|
69
|
-
|
|
74
|
+
// Access push via the injected gtm prop
|
|
75
|
+
this.props.gtm.push({ event: 'purchase', value: 49.99 });
|
|
70
76
|
};
|
|
71
77
|
|
|
72
78
|
render() {
|
|
@@ -74,77 +80,124 @@ class BuyButton extends React.Component {
|
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
|
|
83
|
+
// Wrap any component to get the gtm prop
|
|
84
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(BuyButton);
|
|
78
85
|
```
|
|
79
86
|
|
|
80
87
|
---
|
|
81
88
|
|
|
82
89
|
## Features
|
|
83
90
|
|
|
84
|
-
| Feature
|
|
85
|
-
|
|
86
|
-
| **HOC Pattern**
|
|
87
|
-
| **React 16.0+**
|
|
88
|
-
| **StrictMode-Safe** | No double-fires in development mode
|
|
89
|
-
| **TypeScript**
|
|
90
|
-
| **Consent Mode v2** | Built-in GDPR compliance support
|
|
91
|
+
| Feature | Description |
|
|
92
|
+
| ------------------- | ------------------------------------ |
|
|
93
|
+
| **HOC Pattern** | Works with class components |
|
|
94
|
+
| **React 16.0+** | Compatible with older React versions |
|
|
95
|
+
| **StrictMode-Safe** | No double-fires in development mode |
|
|
96
|
+
| **TypeScript** | Full type definitions included |
|
|
97
|
+
| **Consent Mode v2** | Built-in GDPR compliance support |
|
|
91
98
|
|
|
92
99
|
---
|
|
93
100
|
|
|
94
|
-
##
|
|
101
|
+
## API Reference
|
|
95
102
|
|
|
96
|
-
### `withGtm(Component
|
|
103
|
+
### `withGtm(options)(Component)`
|
|
97
104
|
|
|
98
|
-
|
|
105
|
+
A curried Higher-Order Component that wraps your component and provides GTM functionality.
|
|
99
106
|
|
|
100
107
|
```tsx
|
|
101
|
-
import { withGtm } from '@
|
|
108
|
+
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';
|
|
109
|
+
|
|
110
|
+
const WrappedComponent = withGtm({
|
|
111
|
+
config: {
|
|
112
|
+
containers: 'GTM-XXXXXX',
|
|
113
|
+
dataLayerName: 'dataLayer' // optional
|
|
114
|
+
},
|
|
115
|
+
propName: 'gtm' // optional, defaults to 'gtm'
|
|
116
|
+
})(YourComponent);
|
|
117
|
+
```
|
|
102
118
|
|
|
103
|
-
|
|
104
|
-
render() {
|
|
105
|
-
return <div>{this.props.children}</div>;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
119
|
+
#### Options
|
|
108
120
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
| Option | Type | Default | Description |
|
|
122
|
+
| ---------- | ------------------------ | -------- | ------------------------- |
|
|
123
|
+
| `config` | `CreateGtmClientOptions` | Required | GTM client configuration |
|
|
124
|
+
| `propName` | `string` | `'gtm'` | Name of the injected prop |
|
|
125
|
+
|
|
126
|
+
#### Injected Props
|
|
127
|
+
|
|
128
|
+
The wrapped component receives a prop (default name: `gtm`) with the following API:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
interface LegacyGtmApi {
|
|
132
|
+
client: GtmClient; // Raw GTM client
|
|
133
|
+
push: (value: DataLayerValue) => void; // Push to dataLayer
|
|
134
|
+
setConsentDefaults: (state, options?) => void; // Set consent defaults
|
|
135
|
+
updateConsent: (state, options?) => void; // Update consent state
|
|
136
|
+
}
|
|
116
137
|
```
|
|
117
138
|
|
|
118
|
-
|
|
139
|
+
---
|
|
119
140
|
|
|
120
|
-
|
|
141
|
+
## Usage Examples
|
|
121
142
|
|
|
122
|
-
|
|
123
|
-
import { withGtmPush } from '@react-gtm-kit/react-legacy';
|
|
143
|
+
### Pushing Events
|
|
124
144
|
|
|
145
|
+
```tsx
|
|
125
146
|
class TrackableButton extends React.Component {
|
|
126
147
|
handleClick = () => {
|
|
127
|
-
this.props.
|
|
148
|
+
this.props.gtm.push({
|
|
149
|
+
event: 'button_click',
|
|
150
|
+
button_id: 'main-cta',
|
|
151
|
+
button_text: 'Sign Up'
|
|
152
|
+
});
|
|
128
153
|
};
|
|
129
154
|
|
|
130
155
|
render() {
|
|
131
|
-
return <button onClick={this.handleClick}>
|
|
156
|
+
return <button onClick={this.handleClick}>Sign Up</button>;
|
|
132
157
|
}
|
|
133
158
|
}
|
|
134
159
|
|
|
135
|
-
export default
|
|
160
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(TrackableButton);
|
|
136
161
|
```
|
|
137
162
|
|
|
138
|
-
###
|
|
139
|
-
|
|
140
|
-
Injects consent management props.
|
|
163
|
+
### E-commerce Tracking
|
|
141
164
|
|
|
142
165
|
```tsx
|
|
143
|
-
|
|
166
|
+
class ProductCard extends React.Component {
|
|
167
|
+
trackAddToCart = () => {
|
|
168
|
+
this.props.gtm.push({
|
|
169
|
+
event: 'add_to_cart',
|
|
170
|
+
ecommerce: {
|
|
171
|
+
items: [
|
|
172
|
+
{
|
|
173
|
+
item_id: this.props.product.id,
|
|
174
|
+
item_name: this.props.product.name,
|
|
175
|
+
price: this.props.product.price
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
};
|
|
144
181
|
|
|
182
|
+
render() {
|
|
183
|
+
return (
|
|
184
|
+
<div>
|
|
185
|
+
<h3>{this.props.product.name}</h3>
|
|
186
|
+
<button onClick={this.trackAddToCart}>Add to Cart</button>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(ProductCard);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Managing Consent
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
145
198
|
class CookieBanner extends React.Component {
|
|
146
199
|
acceptAll = () => {
|
|
147
|
-
this.props.updateConsent({
|
|
200
|
+
this.props.gtm.updateConsent({
|
|
148
201
|
ad_storage: 'granted',
|
|
149
202
|
analytics_storage: 'granted',
|
|
150
203
|
ad_user_data: 'granted',
|
|
@@ -152,24 +205,78 @@ class CookieBanner extends React.Component {
|
|
|
152
205
|
});
|
|
153
206
|
};
|
|
154
207
|
|
|
208
|
+
acceptAnalyticsOnly = () => {
|
|
209
|
+
this.props.gtm.updateConsent({
|
|
210
|
+
analytics_storage: 'granted'
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
155
214
|
render() {
|
|
156
|
-
return
|
|
215
|
+
return (
|
|
216
|
+
<div className="cookie-banner">
|
|
217
|
+
<p>We use cookies to improve your experience.</p>
|
|
218
|
+
<button onClick={this.acceptAnalyticsOnly}>Analytics Only</button>
|
|
219
|
+
<button onClick={this.acceptAll}>Accept All</button>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
157
222
|
}
|
|
158
223
|
}
|
|
159
224
|
|
|
160
|
-
export default
|
|
225
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(CookieBanner);
|
|
161
226
|
```
|
|
162
227
|
|
|
163
|
-
###
|
|
228
|
+
### Setting Consent Defaults
|
|
164
229
|
|
|
165
|
-
|
|
230
|
+
```tsx
|
|
231
|
+
class App extends React.Component {
|
|
232
|
+
componentDidMount() {
|
|
233
|
+
// Set consent defaults for EEA users
|
|
234
|
+
this.props.gtm.setConsentDefaults(
|
|
235
|
+
{
|
|
236
|
+
ad_storage: 'denied',
|
|
237
|
+
analytics_storage: 'denied',
|
|
238
|
+
ad_user_data: 'denied',
|
|
239
|
+
ad_personalization: 'denied'
|
|
240
|
+
},
|
|
241
|
+
{ region: ['EEA'] }
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
render() {
|
|
246
|
+
return <YourApp />;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(App);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Custom Prop Name
|
|
166
254
|
|
|
167
255
|
```tsx
|
|
168
|
-
|
|
256
|
+
// Use a custom prop name instead of 'gtm'
|
|
257
|
+
class MyComponent extends React.Component {
|
|
258
|
+
handleClick = () => {
|
|
259
|
+
this.props.analytics.push({ event: 'click' });
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
render() {
|
|
263
|
+
return <button onClick={this.handleClick}>Click</button>;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
169
266
|
|
|
267
|
+
export default withGtm({
|
|
268
|
+
config: { containers: 'GTM-XXXXXX' },
|
|
269
|
+
propName: 'analytics'
|
|
270
|
+
})(MyComponent);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Accessing the Raw Client
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
170
276
|
class AdvancedComponent extends React.Component {
|
|
171
277
|
componentDidMount() {
|
|
172
|
-
|
|
278
|
+
// Wait for GTM to be fully loaded
|
|
279
|
+
this.props.gtm.client.whenReady().then(() => {
|
|
173
280
|
console.log('GTM is ready!');
|
|
174
281
|
});
|
|
175
282
|
}
|
|
@@ -179,45 +286,35 @@ class AdvancedComponent extends React.Component {
|
|
|
179
286
|
}
|
|
180
287
|
}
|
|
181
288
|
|
|
182
|
-
export default
|
|
289
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(AdvancedComponent);
|
|
183
290
|
```
|
|
184
291
|
|
|
185
292
|
---
|
|
186
293
|
|
|
187
|
-
##
|
|
294
|
+
## TypeScript Support
|
|
295
|
+
|
|
296
|
+
Full TypeScript definitions are included:
|
|
188
297
|
|
|
189
298
|
```tsx
|
|
190
|
-
import
|
|
191
|
-
import {
|
|
299
|
+
import React from 'react';
|
|
300
|
+
import { withGtm, LegacyGtmProps } from '@jwiedeman/gtm-kit-react-legacy';
|
|
192
301
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
render() {
|
|
196
|
-
return <div>{this.props.children}</div>;
|
|
197
|
-
}
|
|
302
|
+
interface MyComponentProps extends LegacyGtmProps {
|
|
303
|
+
title: string;
|
|
198
304
|
}
|
|
199
305
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
});
|
|
306
|
+
class MyComponent extends React.Component<MyComponentProps> {
|
|
307
|
+
handleClick = () => {
|
|
308
|
+
// TypeScript knows gtm.push exists
|
|
309
|
+
this.props.gtm.push({ event: 'click' });
|
|
310
|
+
};
|
|
206
311
|
|
|
207
|
-
// Cookie banner component
|
|
208
|
-
class CookieBanner extends React.Component {
|
|
209
312
|
render() {
|
|
210
|
-
return
|
|
211
|
-
<div>
|
|
212
|
-
<button onClick={() => this.props.updateConsent({ analytics_storage: 'granted' })}>
|
|
213
|
-
Accept Analytics
|
|
214
|
-
</button>
|
|
215
|
-
</div>
|
|
216
|
-
);
|
|
313
|
+
return <h1 onClick={this.handleClick}>{this.props.title}</h1>;
|
|
217
314
|
}
|
|
218
315
|
}
|
|
219
316
|
|
|
220
|
-
export default
|
|
317
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(MyComponent);
|
|
221
318
|
```
|
|
222
319
|
|
|
223
320
|
---
|
|
@@ -228,14 +325,18 @@ If you're upgrading your codebase to use hooks, migration is straightforward:
|
|
|
228
325
|
|
|
229
326
|
```tsx
|
|
230
327
|
// Before (react-legacy)
|
|
328
|
+
import { withGtm } from '@jwiedeman/gtm-kit-react-legacy';
|
|
329
|
+
|
|
231
330
|
class Button extends React.Component {
|
|
232
331
|
render() {
|
|
233
|
-
return <button onClick={() => this.props.
|
|
332
|
+
return <button onClick={() => this.props.gtm.push({ event: 'click' })}>Click</button>;
|
|
234
333
|
}
|
|
235
334
|
}
|
|
236
|
-
export default
|
|
335
|
+
export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(Button);
|
|
237
336
|
|
|
238
337
|
// After (react-modern)
|
|
338
|
+
import { useGtmPush } from '@jwiedeman/gtm-kit-react';
|
|
339
|
+
|
|
239
340
|
function Button() {
|
|
240
341
|
const push = useGtmPush();
|
|
241
342
|
return <button onClick={() => push({ event: 'click' })}>Click</button>;
|
|
@@ -247,7 +348,7 @@ function Button() {
|
|
|
247
348
|
## Requirements
|
|
248
349
|
|
|
249
350
|
- React 16.0+
|
|
250
|
-
- `@
|
|
351
|
+
- `@jwiedeman/gtm-kit` (peer dependency)
|
|
251
352
|
|
|
252
353
|
---
|
|
253
354
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jwiedeman/gtm-kit-react-legacy",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Legacy React HOC adapter for GTM Kit - Google Tag Manager integration.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@jwiedeman/gtm-kit": "^1.1.
|
|
43
|
+
"@jwiedeman/gtm-kit": "^1.1.4"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|