Getting started with @d-cat/ddm-core
The DigitalData Manager (DDM) provides an API for centralized access to the DigitalData object in the DOM. In addition the DDM provides an event mechanism for data changes as well as general event handling and persistence. Please note that DDM fully supports Google Tag Manager. Each DDM event, automatically syncs with Google Tag Manager's dataLayer.
Install
npm i @d-cat/ddm-core
Usage
import DDM from '@d-cat/ddm-core';
const dataLayer = new DDM();
Parameters
parameter | type | description |
---|---|---|
historyDD |
{ [index:string] : any } | History dataLayer variables that should be merged with new dataLayer. |
historyDDM |
{e : Array<any>; l: Array<any>; trigger(...args):void; listen(...args):void} | History dataLayer trigger and listeners that should be merged (and executed) with new dataLayer. |
Members
events {name: string, timestamp:number, data?: object}[]
The events array. This keeps track of all events that were triggered using the DDM trigger function. It is publically available using dataLayer.events, which is a direct reference to the events array.
getDDMState (): object
Returns DDM state. This method is mainly used for the DDM debugger (chrome extensions) and debugging options.
Example
const { props } = dataLayer.getDDMState();
set <T>(path: string, value: T, persist?: boolean, ttl?: int): T
Stores an object at a given dot notated path. Existing properties with the same name will be overwritten; except if an object already exists at the given path, the provided data will be merged with the existing object.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to store. |
value |
* | The value that you want to store. |
persist |
{boolean} | Whether to persist this key or not. Defaults to false. |
ttl |
integer | Number of minutes to persist the value. Defaults to 30 minutes. |
Example
dataLayer.set('dot.notated.path', 'value');
get <T>(path?: string, defaultValue?: T, createNonExisting?: boolean): T
Retrieve data from DDM Core for a given dot-notated path, or the entire dataLayer when no path given. If no value/object is available at the path, you can optionally create the value/object at that path using a provided value. The later is merely for convenience. When no path is given, the entire dataLayer will be returned.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to retrieve. Or no path if you want to retreive entire dataLayer. |
defaultValue |
* | An optional defaultValue that you want to use if no object/property is available at the provided path. |
createNonExisting |
{boolean} | Determines if the object/property should be added to DigitalData, using the defaultValue, if it does not exist. |
Example
const { user } = dataLayer.get('user.id');
has (path: string): boolean
Determines whether the dataLayer has a value at the given path. Returns true if the value at the given path is not undefined. False otherwise.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to retrieve. Or no path if you want to retreive entire dataLayer. |
Example
if (dataLayer.has('user.id')) {
console.log('yaay');
}
empty (path: string): boolean
Determines whether the object at the given path is null, an empty object/array, an empty string or does not exist at all. Take note that a string consisting of only whitespace is also regarded as empty and that integer values are never regarded as being empty.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to retrieve. Or no path if you want to retreive entire dataLayer. |
Example
if (dataLayer.empty('user.id')) {
console.log('empty');
}
push <T>(path: string, value: T): T
Pushes a value into an array in the DigitalData object. If an array does not exist yet at the given path, or the object/property at the given path is not an array, an array will be created.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to store. |
value |
* | The value that you want to store. |
Example
dataLayer.push('dot.notated.path.to.array', 'value-to-push-into-array');
change (path: string, onlyInvokeOnChanges: boolean, handler: () => void, id: string): { unlisten: () => void }
Adds a "change" listener to the dataLayer. Change listeners are being invoked whenever there is a change in the dataLayer where the path that the listener is interested in is involved. The handler is also invoked when the listener is registered and there is already data in the dataLayer for the path it wants to listen to. The path is dot notated and can use two types of wildcards. * and **.
Wildcard listeners using _ as the wildcard are invoked whenever there is a change on the same node-level as the node that was changed. For instance, a listener on user._ would be invoked whenever a dataLayer variable would change. It will not be changed for changes in for instance user.address.zipcode. Wildcard listeners using ** as the wildcard are invoked whenever there is a change on the same node-level as the node that was changed, as well as deeper node levels. For instance, in the previous situation of user.address.zipcode, listeners for user.** will also be invoked.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to listen to. |
onlyInvokeOnChanges |
boolean | Boolean to indicate that the handler should only be invoked when changes occur. |
handler |
function | TThe handler that has to be invoked. |
id |
string | Descriptive name. |
Example
// Add a change listener on only the user.products key in the dataLayer
dataLayer.change('user.products', true, (data: any) => console.log(data), 'unique - key - string');
// Add a change listener on user.products and any of it's direct children.
dataLayer.change('user.products.*', true, (data: any) => console.log(data), 'unique - key - string');
// Add a change listener on user.products and any of it's children or grandchildren.
dataLayer.change('user.products.**', false, () => console.log('yaay'), 'unique - key - string');
// Add a change listener on user.id, but do not invoke the handler function if the dataLayer already holds a value for user.id. Only invoke the handler when the property user.id changes.
const changeListener = dataLayer.change('user.id', true, (data: any) => console.log('yaay'), 'unique - key - string');
// remove change listener
changeListener.unlisten();
erase (path: string): void
Erases an object from the dataLayer at the provided path. Consequently also unpersists possibly persisted objects at the provided path and any path underneath the provided path.
Parameters
parameter | type | description |
---|---|---|
path |
string | The dot notated path of the object/property that you want to erase. |
Example
dataLayer.erase('dot.notated.path.to.object.that.must.be.erased');
trigger (path: string, payload?: object): void
This method can be called to trigger an event. It will look up listeners for the provided name (dot notated, wild cards apply) and invoke all listeners that were interested in the event. The listeners will recieve an event object, which consists of the provided payload.
Parameters
parameter | type | description |
---|---|---|
eventName |
string | Name of the event (dot notated, wildcards apply). |
payload |
object | The payload of the event. Payload contains data or dd key. Defaults to an empty object. |
Examples
dataLayer.trigger('name-of-event');
Trigger an event and provide some event data. Handlers of listeners to this event retrieve the data.
dataLayer.trigger('name-of-event', {
data: {
key: 'value',
},
});
Trigger an event and provide data that needs to be put in DDM Core. Note that the dd key is a wildcard.
dataLayer.trigger("name-of-event", {
"dd": {
"key", "value"
}
});
listen (name: string[]|string, invokeHandlerOnHistoricalEvents: boolean, handler: () => void, id: string): void
Adds a event listener. These listeners are being called when the trigger()
method is being called and the name of the listener matches the name that was provided to the trigger. This can be used as a general event mechanism. The name is in fact a dot notated path and the same wildcards as for change listeners apply.
By default, the handler function will be called for historical events as well.
It is possible to provide multiple eventnames as an array. All the events in the array must have been triggered before the handler is being called.
Parameters
parameter | type | description |
---|---|---|
name |
string|string[] | Name of event(s) to listen to (dot notated, wildcards apply). |
invokeHandlerOnHistoricalEvents |
boolean | Boolean that indicates if the handler should also be invoked for historical events. Default is true. |
handler |
function | The handler that has to be invoked. |
id |
string | The unique identifier given to this handler. This is used for error handling to aid in debugging. |
Binding scopes
Binding scopes to the listen method is possible. The binded scope becomes available within the scope of the listener.
dataLayer.listen('bind.function', false, incrementVal.bind(this));
dataLayer.trigger(name);
However when unlistening to the event, some additional configuration has to be made.
const bindedHandler = () => console.log(`I'm binded.`);
// Note the id is NOT set: and thus the key is either .toString or name.
dataLayer.listen('boundFunction', false, bindedHandler.bind(this));
// Note the id is NOT set: and thus the key is either .toString or name.
dataLayer.unlisten('boundFunction', bindedHandler.bind(this));
dataLayer.trigger('boundFunction'); // nothing happens --> valid unlistening
const secondBindedHandler = () => console.log(`I'm binded: 2.`);
// Note the id is set: and thus also used as key
dataLayer.listen('boundFunction', false, bindedHandler.bind(this), id);
// Note the id is set: and thus also used as key
dataLayer.unlisten('boundFunction', secondBindedHandler.bind(this), id);
dataLayer.trigger('boundFunction'); // nothing happens --> valid unlistening
Examples
By default, the handler function will be called for historical events as well. You can disable it by passing a boolean.
dataLayer.listen('dd.loaded', false, (e: any) => console.log(e), 'descriptive name of this listener');
It is possible to provide multiple eventnames as an array. All the events in the array must have been triggered each time before the handler is being called once.
listen(['trigger.one', 'trigger.two'], false, (e: any) => console.log(e), 'descriptive name of this listener');
unlisten (path: string, handler?: (e?: object) => void, id?: string): void
Removes an named listener for a given name. This can not be used for listeners that have been registered using dataLayer.listen()
with an anonymous function declaration. A reference to the function is required. See examples.
Parameters
parameter | type | description |
---|---|---|
path |
string | Name of an event to remove the listener for (dot notated, wildcards apply). |
handler |
function | The handler that was to be invoked. |
id |
string | Unique key linked to a handler. |
Examples
// Create a non-anonymous handler function (Only non-anonymous functions can be unregistered using dataLayer.unlisten)
let myHandler = (e: data) => console.log(e);
// Register the handler function as a listener to events with the name "myEvent"
dataLayer.listen('myEvent', myHandler);
// Unregister the handler to stop listening for events with the name "myEvent"
dataLayer.unlisten('myEvent', myHandler);
isTriggered (eventName: string, arr?: Array<any> = dataLayer.events): boolean
This function determines if an event with a given name has been triggered before. Returns true if it was, false otherwise.
Parameters
parameter | type | description |
---|---|---|
eventName |
string | The name of the event |
arr |
{name: string}[] | An events array. |
Example
if (dataLayer.isTriggered('ddm.loaded')) {
console.log('ddm.loaded fired');
}
setCookie (name: string, value: string, days?: number, path?: string, domain?: string): void
Sets a cookie with the given name and value. If a value is specified for days an expiry valye will be set for the cookie. The path of the cookie is defaulted to "/".
Parameters
parameter | type | description |
---|---|---|
name |
string | The name of the cookie to set. |
value |
string | The value of the cookie to set. |
days |
integer | The number of days until the cookie expires. |
path |
string | The path of the cookie. Defaults to "/" |
domain |
string | The domain of the cookie. Defaults to the base of the current domain, including subdomains (leading dot), eg: .example.com |
Example
dataLayer.setCookie('randomCookie', 1, 100);
getCookie (cookieName: string): string
Gets a cookie with a given name.
Parameters
parameter | type | description |
---|---|---|
name |
string | The name of the cookie. |
Example
const val = dataLayer.getCookie('randomCookie');
removeCookie (name: string, path?: string): void
Delete a cookie valid to the path of the current page.
Parameters
parameter | type | description |
---|---|---|
name |
string | The name of the cookie. |
path |
string | The path of the cookie. |
Example
dataLayer.removeCookie('randomCookie');
persist (path: string, ttl?: number): void
Registers a dot-notated path of DDM Core's datalayer as persistent. A TTL can be provided in minutes how long the value should be persisted. Defaults to 30 minutes. This method is also called during the initialization of DDM to register the default paths that are to be persisted.
Parameters
parameter | type | description |
---|---|---|
path |
string | Dot-notated path into DDM Core's datalayer. |
ttl |
number | Expiration in minutes. Default is 30. |
Examples
dataLayer.persist('user', 60);
unpersist (path: string): void
Unpersists a given path and removes all change listeners.
Parameters
parameter | type | description |
---|---|---|
path |
string | Dot-notated path into DDM Core's datalayer to unpersist. |
Examples
dataLayer.unpersist('user');
getUrlParam (param: string): string
Returns the value of a parameter in the HTTP URL string of the current URL.
Parameters
parameter | type | description |
---|---|---|
paramName |
string | The name of the parameter to search for. |
Examples
const param = dataLayer.getUrlParam('user');
getRefParam (param: string): string
Returns the value of a parameter in the HTTP Referer URL string.
Parameters
parameter | type | description |
---|---|---|
paramName |
string | The name of the parameter to search for. |
Examples
const param = dataLayer.getRefParam('user');
isObject (obj: any): boolean
Checks whether a given object is in fact an Object.
Parameters
parameter | type | description |
---|---|---|
obj |
any | The object to test |
Examples
if (dataLayer.isObject({})) {
}
isArray (arr: any): boolean
Checks whether a given object is in fact an Array.
Parameters
parameter | type | description |
---|---|---|
arr |
any | The object to test |
Examples
if (dataLayer.isArray({})) {
}
isInteger (int: any): boolean
Checks whether a given object is an Integer.
Parameters
parameter | type | description |
---|---|---|
int |
any | The object to test |
Examples
if (dataLayer.isInteger({})) {
}
isString (str: any): boolean
Checks whether a given object is an string.
Parameters
parameter | type | description |
---|---|---|
str |
any | The object to test |
Examples
if (dataLayer.isString({})) {
}
cloneObject (obj: object): object
Method to clone an object using JSON (de)serialization.
Parameters
parameter | type | description |
---|---|---|
obj |
object | The object to clone |
Examples
const newObj = dataLayer.cloneObject({});
mergeObjects (destination: object, source: object): object
Deep merge a source object into a destination object, modifying the destination object.
Parameters
parameter | type | description |
---|---|---|
destination |
object | The destination object where to merge into. |
source |
object | The source object that needs to be merged into the destination object. |
Examples
const newObj = dataLayer.mergeObjects(
{
data: {
a: 1,
},
},
{
data: {
b: 1,
},
},
);