@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.
Files changed (2) hide show
  1. package/README.md +187 -86
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # @react-gtm-kit/react-legacy
1
+ # @jwiedeman/gtm-kit-react-legacy
2
2
 
3
- [![CI](https://github.com/jwiedeman/react-gtm-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/jwiedeman/react-gtm-kit/actions/workflows/ci.yml)
4
- [![Coverage](https://codecov.io/gh/jwiedeman/react-gtm-kit/graph/badge.svg?flag=react-legacy)](https://codecov.io/gh/jwiedeman/react-gtm-kit)
5
- [![npm version](https://img.shields.io/npm/v/@react-gtm-kit/react-legacy.svg)](https://www.npmjs.com/package/@react-gtm-kit/react-legacy)
6
- [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@react-gtm-kit/react-legacy)](https://bundlephobia.com/package/@react-gtm-kit/react-legacy)
3
+ [![CI](https://github.com/jwiedeman/GTM-Kit/actions/workflows/ci.yml/badge.svg)](https://github.com/jwiedeman/GTM-Kit/actions/workflows/ci.yml)
4
+ [![Coverage](https://codecov.io/gh/jwiedeman/GTM-Kit/graph/badge.svg?flag=react-legacy)](https://codecov.io/gh/jwiedeman/GTM-Kit)
5
+ [![npm version](https://img.shields.io/npm/v/@jwiedeman/gtm-kit-react-legacy.svg)](https://www.npmjs.com/package/@jwiedeman/gtm-kit-react-legacy)
6
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@jwiedeman/gtm-kit-react-legacy)](https://bundlephobia.com/package/@jwiedeman/gtm-kit-react-legacy)
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![React](https://img.shields.io/badge/React-16.0+-61DAFB.svg?logo=react)](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 @react-gtm-kit/core @react-gtm-kit/react-legacy
20
+ npm install @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
21
21
  ```
22
22
 
23
23
  ```bash
24
- yarn add @react-gtm-kit/core @react-gtm-kit/react-legacy
24
+ yarn add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-react-legacy
25
25
  ```
26
26
 
27
27
  ```bash
28
- pnpm add @react-gtm-kit/core @react-gtm-kit/react-legacy
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 `@react-gtm-kit/react-legacy` if:
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 [`@react-gtm-kit/react-modern`](https://www.npmjs.com/package/@react-gtm-kit/react-modern) which uses hooks.
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 App
48
+ ### Step 1: Wrap Your Root Component
49
49
 
50
50
  ```tsx
51
- import { withGtm } from '@react-gtm-kit/react-legacy';
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
- export default withGtm(App, { containers: 'GTM-XXXXXX' });
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: Push Events
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 { withGtmPush } from '@react-gtm-kit/react-legacy';
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
- this.props.gtmPush({ event: 'purchase', value: 49.99 });
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
- export default withGtmPush(BuyButton);
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 | Description |
85
- |---------|-------------|
86
- | **HOC Pattern** | Works with class components |
87
- | **React 16.0+** | Compatible with older React versions |
88
- | **StrictMode-Safe** | No double-fires in development mode |
89
- | **TypeScript** | Full type definitions included |
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
- ## Available HOCs
101
+ ## API Reference
95
102
 
96
- ### `withGtm(Component, config)`
103
+ ### `withGtm(options)(Component)`
97
104
 
98
- Wraps your root component and initializes GTM.
105
+ A curried Higher-Order Component that wraps your component and provides GTM functionality.
99
106
 
100
107
  ```tsx
101
- import { withGtm } from '@react-gtm-kit/react-legacy';
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
- class App extends React.Component {
104
- render() {
105
- return <div>{this.props.children}</div>;
106
- }
107
- }
119
+ #### Options
108
120
 
109
- export default withGtm(App, {
110
- containers: 'GTM-XXXXXX',
111
- dataLayerName: 'dataLayer', // optional
112
- onBeforeInit: (client) => {
113
- // Set consent defaults here
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
- ### `withGtmPush(Component)`
139
+ ---
119
140
 
120
- Injects a `gtmPush` prop for pushing events.
141
+ ## Usage Examples
121
142
 
122
- ```tsx
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.gtmPush({ event: 'button_click', button_id: 'main-cta' });
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}>Click Me</button>;
156
+ return <button onClick={this.handleClick}>Sign Up</button>;
132
157
  }
133
158
  }
134
159
 
135
- export default withGtmPush(TrackableButton);
160
+ export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(TrackableButton);
136
161
  ```
137
162
 
138
- ### `withGtmConsent(Component)`
139
-
140
- Injects consent management props.
163
+ ### E-commerce Tracking
141
164
 
142
165
  ```tsx
143
- import { withGtmConsent } from '@react-gtm-kit/react-legacy';
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 <button onClick={this.acceptAll}>Accept All</button>;
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 withGtmConsent(CookieBanner);
225
+ export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(CookieBanner);
161
226
  ```
162
227
 
163
- ### `withGtmClient(Component)`
228
+ ### Setting Consent Defaults
164
229
 
165
- Injects the raw GTM client instance.
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
- import { withGtmClient } from '@react-gtm-kit/react-legacy';
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
- this.props.gtmClient.whenReady().then(() => {
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 withGtmClient(AdvancedComponent);
289
+ export default withGtm({ config: { containers: 'GTM-XXXXXX' } })(AdvancedComponent);
183
290
  ```
184
291
 
185
292
  ---
186
293
 
187
- ## Consent Mode v2 (GDPR)
294
+ ## TypeScript Support
295
+
296
+ Full TypeScript definitions are included:
188
297
 
189
298
  ```tsx
190
- import { withGtm, withGtmConsent } from '@react-gtm-kit/react-legacy';
191
- import { consentPresets } from '@react-gtm-kit/core';
299
+ import React from 'react';
300
+ import { withGtm, LegacyGtmProps } from '@jwiedeman/gtm-kit-react-legacy';
192
301
 
193
- // Root component with consent defaults
194
- class App extends React.Component {
195
- render() {
196
- return <div>{this.props.children}</div>;
197
- }
302
+ interface MyComponentProps extends LegacyGtmProps {
303
+ title: string;
198
304
  }
199
305
 
200
- export default withGtm(App, {
201
- containers: 'GTM-XXXXXX',
202
- onBeforeInit: (client) => {
203
- client.setConsentDefaults(consentPresets.eeaDefault, { region: ['EEA'] });
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 withGtmConsent(CookieBanner);
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.gtmPush({ event: 'click' })}>Click</button>;
332
+ return <button onClick={() => this.props.gtm.push({ event: 'click' })}>Click</button>;
234
333
  }
235
334
  }
236
- export default withGtmPush(Button);
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
- - `@react-gtm-kit/core` (peer dependency)
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.2",
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.2"
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"