Comparing version 1.0.2 to 1.0.3
@@ -1,4 +0,2 @@ | ||
export declare function setClient(apiSecret: any, measurementId: any, clientId: any): void; | ||
export declare function readClient(): void; | ||
export declare function sendHit(events: any): void; | ||
export declare function testSendHit(events: any): void; | ||
export declare function GA4MPClient(apiSecret: any, measurementId: any, clientId: any): void; | ||
export declare function createClient(apiSecret: any, measurementId: any, clientId: any): any; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.testSendHit = exports.sendHit = exports.readClient = exports.setClient = void 0; | ||
exports.createClient = exports.GA4MPClient = void 0; | ||
const axios = require('axios'); | ||
var API_SECRET; // GA > Admin > Data Streams > choose your stream > Measurement Protocol > Create | ||
var MEASUREMENT_ID; // GA Admin > Data Streams > choose your stream > Measurement ID | ||
var CLIENT_ID; // https://developers.google.com/identity/one-tap/web/guides/get-google-api-clientid | ||
var GA_ENDPOINT; | ||
var DEBUG_ENDPOINT; | ||
function setClient(apiSecret, measurementId, clientId) { | ||
API_SECRET = apiSecret; | ||
MEASUREMENT_ID = measurementId; | ||
CLIENT_ID = clientId; | ||
GA_ENDPOINT = `https://www.google-analytics.com/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`; | ||
DEBUG_ENDPOINT = `https://www.google-analytics.com/debug/mp/collect?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`; | ||
// This is the interface/object for communicating with GA4MP | ||
function GA4MPClient(apiSecret, measurementId, clientId) { | ||
// Vars for GA4 connection | ||
this.API_SECRET = apiSecret; // GA > Admin > Data Streams > choose your stream > Measurement Protocol > Create | ||
this.MEASUREMENT_ID = measurementId; // GA Admin > Data Streams > choose your stream > Measurement ID | ||
this.CLIENT_ID = clientId; // https://developers.google.com/identity/one-tap/web/guides/get-google-api-clientid | ||
this.GA_ENDPOINT = `https://www.google-analytics.com/mp/collect?measurement_id=${this.MEASUREMENT_ID}&api_secret=${this.API_SECRET}`; | ||
this.DEBUG_ENDPOINT = `https://www.google-analytics.com/debug/mp/collect?measurement_id=${this.MEASUREMENT_ID}&api_secret=${this.API_SECRET}`; | ||
// Outputs the connection details to console | ||
this.readClientInfo = function () { | ||
console.log(` | ||
*** Connection details for GA4 Connection *** | ||
API_SECRET: ${this.API_SECRET} | ||
MEASUREMENT_ID: ${this.MEASUREMENT_ID} | ||
CLIENT_ID: ${this.CLIENT_ID} | ||
GA_ENDPOINT: ${this.GA_ENDPOINT} | ||
DEBUG_ENDPOINT: ${this.DEBUG_ENDPOINT} | ||
`); | ||
}; | ||
// For preserving paramaters that will be attached to all events | ||
this.constantParams = {}; | ||
//Sets a constant parameter for each hit sent to GA (pagepath, custom dimension) | ||
this.setConstantParam = function (key, value) { | ||
this.constantParams[key] = value; | ||
}; | ||
//Removes a constant parameter listed in this.constantParams | ||
this.unsetConstantParam = function (key) { | ||
delete this.constantParams[key]; | ||
}; | ||
// Adds key/value pairs from this.constantParams to each event | ||
this.addConstantParamsToEvents = function (events) { | ||
for (var i = 0; i < events.length; i++) { | ||
for (var param in this.constantParams) { | ||
events[i].params[param] = this.constantParams[param]; | ||
} | ||
} | ||
}; | ||
// For async send of hits | ||
this.hitBuffer = []; | ||
// Send data to Google analytics | ||
// Allows for postponing hits send for later | ||
this.send = function (events, postpone = false) { | ||
var eventMax = events.length > 25; | ||
this.checkPredefinedEventParams(events); | ||
this.addConstantParamsToEvents(events); | ||
this.nullParamCheck(events); | ||
if (postpone) { | ||
events.forEach(event => this.hitBuffer.push(event)); | ||
} | ||
else { | ||
if (eventMax) { | ||
this.sendLargeEventCount(events); | ||
} | ||
else { | ||
axios.post(this.GA_ENDPOINT, { | ||
client_id: this.CLIENT_ID, | ||
events: events | ||
}).then(res => { | ||
// console.log(res) | ||
}).catch(error => { | ||
console.log(error); | ||
}); | ||
} | ||
} | ||
}; | ||
// Sends all postponed hits held in this.hitBuffer | ||
this.flushBuffer = function () { | ||
this.sendLargeEventCount(this.hitBuffer); | ||
}; | ||
// Sends out more than 25 hits at a time | ||
this.sendLargeEventCount = function (events) { | ||
var eventBlock; | ||
while (events.length > 0) { | ||
eventBlock = events.splice(25); | ||
this.send(events); | ||
events = eventBlock; | ||
} | ||
}; | ||
// Checks that if a user sends a predefined event, has required params | ||
// https://support.google.com/analytics/answer/9322688?hl=en&ref_topic=9756175 | ||
this.checkPredefinedEventParams = function (events) { | ||
// All pre-defined events/params | ||
var eventList = { | ||
'ad_click': ['ad_event_id'], | ||
'ad_exposure': ['firebase_screen', 'firebase_screen_id', 'firebase_screen_class', 'exposure_time'], | ||
'ad_impression': ['ad_event_id'], | ||
'ad_query': ['ad_event_id'], | ||
'ad_reward': ['ad_unit_id', 'reward_type', 'reward_value'], | ||
'add_payment_info': ['coupon', 'currency', 'items', 'payment_type', 'value'], | ||
'add_shipping_info': ['coupon', 'currency', 'items', 'shipping_tier', 'value'], | ||
'add_to_cart': ['currency', 'items', 'value'], | ||
'add_to_wishlist': ['currency', 'items', 'value'], | ||
'adunit_exposure': ['firebase_screen', 'firebase_screen_id', 'firebase_screen_class', 'exposure_time'], | ||
'app_clear_data': [], | ||
'app_exception': ['fatal', 'timestamp', 'engagement_time_msec'], | ||
'app_remove': [], | ||
'app_store_refund': ['product_id', 'value', 'currency', 'quantity'], | ||
'app_store_subscription_cancel': ['product_id', 'price', 'value', 'currency', 'cancellation_reason'], | ||
'app_store_subscription_convert': ['product_id', 'price', 'value', 'currency', 'quantity'], | ||
'app_store_subscription_renew': ['product_id', 'price', 'value', 'currency', 'quantity', 'renewal_count'], | ||
'app_update': ['previous_app_version'], | ||
'begin_checkout': ['coupon', 'currency', 'items', 'value'], | ||
'click': [], | ||
'dynamic_link_app_open': ['source', 'medium', 'campaign', 'link_id', 'accept_time'], | ||
'dynamic_link_app_update': ['source', 'medium', 'campaign', 'link_id', 'accept_time'], | ||
'dynamic_link_first_open': ['source', 'medium', 'campaign', 'link_id', 'accept_time'], | ||
'earn_virtual_currency': ['virtual_currency_name', 'value'], | ||
'error': ['firebase_error', 'firebase_error_value'], | ||
'file_download': ['file_extension', 'file_name', 'link_classes', 'link_domain', 'link_id', 'link_text', 'link_url'], | ||
'firebase_campaign': ['source', 'medium', 'campaign', 'term', 'content', 'gclid', 'aclid', 'cp1', 'anid', 'click_timestamp', 'campaign_info_source'], | ||
'firebase_in_app_message_action': ['message_name', 'message_device_time', 'message_id'], | ||
'firebase_in_app_message_dismiss': ['message_name', 'message_device_time', 'message_id'], | ||
'firebase_in_app_message_impression': ['message_name', 'message_device_time', 'message_id'], | ||
'first_open': ['previous_gmp_app_id', 'updated_with_analytics', 'previous_first_open_count', 'system_app', 'system_app_update', 'deferred_analytics_collection', 'reset_analytics_cause', 'engagement_time_msec'], | ||
'first_visit': [], | ||
'generate_lead': ['value', 'currency'], | ||
'in_app_purchase': ['product_id', 'price', 'value', 'currency', 'quantity', 'subscription', 'free_trial', 'introductory_price'], | ||
'join_group': ['group_id'], | ||
'level_end': ['level_name', 'success'], | ||
'level_start': ['level_name'], | ||
'level_up': ['character', 'level'], | ||
'login': ['method'], | ||
'notification_dismiss': ['message_name', 'message_time', 'message_device_time', 'message_id', 'topic', 'label', 'message_channel'], | ||
'notification_foreground': ['message_name', 'message_time', 'message_device_time', 'message_id', 'topic', 'label', 'message_channel', 'message_type'], | ||
'notification_open': ['message_name', 'message_time', 'message_device_time', 'message_id', 'topic', 'label', 'message_channel'], | ||
'notification_receive': ['message_name', 'message_time', 'message_device_time', 'message_id', 'topic', 'label', 'message_channel', 'message_type'], | ||
'notification_send': ['message_name', 'message_time', 'message_device_time', 'message_id', 'topic', 'label', 'message_channel'], | ||
'os_update': ['previous_os_version'], | ||
'page_view': ['page_location', 'page_referrer'], | ||
'post_score': ['level', 'character', 'score'], | ||
'purchase': ['affiliation', 'coupon', 'currency', 'items', 'transaction_id', 'shipping', 'tax', 'value'], | ||
'refund': ['transaction_id', 'value', 'currency', 'tax', 'shipping', 'items'], | ||
'remove_from_cart': ['currency', 'items', 'value'], | ||
'screen_view': ['firebase_screen', 'firebase_screen_class', 'firebase_screen_id', 'firebase_previous_screen', 'firebase_previous_class', 'firebase_previous_id', 'engagement_time_msec'], | ||
'scroll': [], | ||
'search': ['search_term'], | ||
'select_content': ['content_type', 'item_id'], | ||
'select_item': ['items', 'item_list_name', 'item_list_id'], | ||
'select_promotion': ['items', 'promotion_id', 'promotion_name', 'creative_name', 'creative_slot', 'location_id'], | ||
'session_start': [], | ||
'share': ['content_type', 'item_id'], | ||
'sign_up': ['method'], | ||
'view_search_results': ['search_term'], | ||
'spend_virtual_currency': ['item_name', 'virtual_currency_name', 'value'], | ||
'tutorial_begin': [], | ||
'tutorial_complete': [], | ||
'unlock_achievement': ['achievement_id'], | ||
'user_engagement': ['engagement_time_msec'], | ||
'video_start': ['video_current_time', 'video_duration', 'video_percent', 'video_provider', 'video_title', 'video_url', 'visible'], | ||
'video_progress': ['video_current_time', 'video_duration', 'video_percent', 'video_provider', 'video_title', 'video_url', 'visible'], | ||
'video_complete': ['video_current_time', 'video_duration', 'video_percent', 'video_provider', 'video_title', 'video_url', 'visible'], | ||
'view_cart': ['currency', 'items', 'value'], | ||
'view_item': ['currency', 'items', 'value'], | ||
'view_item_list': ['items', 'item_list_name', 'item_list_id'], | ||
'view_promotion': ['items', 'promotion_id', 'promotion_name', 'creative_name', 'creative_slot', 'location_id'], | ||
}; | ||
for (var i = 0; i < events.length; i++) { | ||
if (eventList[events[i].name] !== undefined) { | ||
for (var eventParam in eventList[events[i].name]) { | ||
if (events[i].params[eventList[events[i].name][eventParam]] === undefined) { | ||
console.log(`Missing a recommened parameter "${eventList[events[i].name][eventParam]}" for "${events[i].name}"`); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
// Removes keys === null as ga4 won't accept the hit | ||
this.nullParamCheck = function (events) { | ||
for (var i = 0; i < events.length; i++) { | ||
for (var param in events[i].params) { | ||
if (events[i].params[param] === null) { | ||
console.log(`Removed null param for '${param}' in '${events[i].name}'`); | ||
delete events[i].params[param]; | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
exports.setClient = setClient; | ||
function readClient() { | ||
console.log("API_SECRET: " + API_SECRET); | ||
console.log("MEASUREMENT_ID: " + MEASUREMENT_ID); | ||
console.log("CLIENT_ID: " + CLIENT_ID); | ||
console.log("GA_ENDPOINT: " + GA_ENDPOINT); | ||
console.log("DEBUG_ENDPOINT: " + DEBUG_ENDPOINT); | ||
exports.GA4MPClient = GA4MPClient; | ||
function createClient(apiSecret, measurementId, clientId) { | ||
let newConnection = new GA4MPClient(apiSecret, measurementId, clientId); | ||
return newConnection; | ||
} | ||
exports.readClient = readClient; | ||
/* | ||
SendHit: events must match the array format: | ||
// [{ | ||
name: <event_name>, | ||
params: {}, | ||
},{ | ||
name: <event_name>, | ||
params: {}, | ||
}] | ||
Can send up to 25 events at once | ||
Verify event and params here: | ||
https://developers.google.com/analytics/devguides/collection/ga4/events | ||
*/ | ||
function sendHit(events) { | ||
axios.post(GA_ENDPOINT, { | ||
client_id: CLIENT_ID, | ||
events: events | ||
}).then(res => { | ||
console.log(res); | ||
}).catch(error => { | ||
console.log(error); | ||
}); | ||
} | ||
exports.sendHit = sendHit; | ||
function testSendHit(events) { | ||
axios.post(DEBUG_ENDPOINT, { | ||
client_id: CLIENT_ID, | ||
events: events | ||
}).then(res => { | ||
console.log(`statusCode: ${res.statusCode}`); | ||
console.log(res); | ||
}).catch(error => { | ||
console.log(error); | ||
}); | ||
} | ||
exports.testSendHit = testSendHit; | ||
exports.createClient = createClient; |
{ | ||
"name": "ga4-mp", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "Send data to Google Analytics 4 using Measurement Protocol", | ||
@@ -29,3 +29,4 @@ "main": "dist/index.js", | ||
"http": "0.0.1-security" | ||
} | ||
}, | ||
"devDependencies": {} | ||
} |
# Google Analytics GA4 Measurement Protocol Library | ||
This library provides an interface for sending data to Google Analytics 4 properties using Measurement Protocol. | ||
**NOTE** Google Analytics 4 is in Alpha as of the latest update | ||
## Use | ||
BSD 3-Clause license can be found in ./LICENSE | ||
## Contact | ||
analytics-help@adswerve.com | ||
## Compatible with | ||
- Node.js version 8+ | ||
- es2015 | ||
## To use | ||
## Installation | ||
### Setup | ||
ga4mp = require('ga4-mp') | ||
ga4mp.setClient(apiSecret, measurementId, clientId); | ||
```sh | ||
npm install -s ga4-mp | ||
``` | ||
### Send Hits to GA4 Account | ||
ga4mp.sendHit(<events>) | ||
## Setup | ||
### Test Hits on GA4 MP debug endpoint | ||
ga4mp.testSendHit(<events>) | ||
```js | ||
ga4mp = require('ga4-mp'); | ||
let ga4 = ga4mp.createClient(apiSecret, measurementId, clientId); | ||
``` | ||
## Send Hits to GA4 Account | ||
You can send events to GA4 as they happen or batch them to be sent at another time of your choosing. | ||
### Send immediately | ||
```js | ||
ga4.send(<events>); | ||
``` | ||
### Send later | ||
```js | ||
ga4.send(<events>, true); // Set postpone flag | ||
ga4.flushBuffer(); // Send all postponed events | ||
``` | ||
### Events passed to send() | ||
```js | ||
var events = [ | ||
{ | ||
name : 'add_to_cart', | ||
params : { | ||
currency : 'USD', | ||
items : ['Pokémon cards'], | ||
value : "4.99" | ||
} | ||
}, | ||
{ | ||
name : 'app_update', | ||
params : { | ||
previous_app_version : '4.6' | ||
} | ||
} | ||
] | ||
``` | ||
Events are expected to be passed to the send() function within an array and matching the object schema found in the [Google Analytics 4 documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#send_an_event). | ||
## Additional Features | ||
### Set and unset a constant parameter | ||
```js | ||
ga4.setConstantParam(key, value); // Set a constant | ||
ga4.unsetConstantParam(key); // Remove a constant | ||
``` | ||
Set custom dimensions/metrics, country codes, etc. for all outgoing events. You can unset them too. | ||
### Output connection details | ||
```js | ||
ga4.readClientInfo(); | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15745
204
88
1