Skip to content

Commit

Permalink
Merge pull request #132 from rudderlabs/merge_prod
Browse files Browse the repository at this point in the history
Merge prods ---> master
  • Loading branch information
sayan-mitra authored Sep 8, 2020
2 parents 908c8b9 + 47a0433 commit 5239627
Show file tree
Hide file tree
Showing 10 changed files with 6,087 additions and 3,078 deletions.
6 changes: 3 additions & 3 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{
"loose": true
}
]
],
"ignore": ["node_modules/**",]
],
["@babel/plugin-transform-arrow-functions"]
]
}
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,37 @@ rudderanalytics.ready(
```
For a detailed technical documentation and troubleshooting guide on the RudderStack’s JavaScript SDK, click [here](https://docs.rudderlabs.com/sdk-integration-guide/getting-started-with-javascript-sdk).

# [](https://github.com/rudderlabs/rudder-sdk-js/blob/master/README.md#querystring-api)Querystring API

Rudder's Querystring API allows you to trigger `track`, `identify` calls using query parameters. If you pass the following parameters in the URL, then it will trigger the corresponding sdk api call.

For example,

```
http://hostname.com/?ajs_uid=12345&ajs_event=test%20event&ajs_aid=abcde&ajs_prop_testProp=prop1&ajs_trait_name=Firstname+Lastname
```
For the above URL, the below sdk calls will be triggered.

```
rudderanalytics.identify("12345", {name: "Firstname Lastname"});
rudderanalytics.track("test event", {testProp: "prop1"});
rudderanalytics.setAnonymousId("abcde");
```

You may use the below parameters as querystring parameter and trigger the corresponding call.

`ajs_uid` : Will make a `rudderanalytics.identify()` call with `userId` having the value of the parameter value.

`ajs_aid` : Will make a `rudderanalytics.setAnonymousId()` call with `anonymousId` having the value of the parameter value.

`ajs_event` : Will make a `rudderanalytics.track()` call with `event` name as parameter value.

`ajs_prop_<property>` : If `ajs_event` is passed as querystring, value of this parameter will populate the `properties` of the corresponding event in the `track` call.

`ajs_trait_<trait>` : If `ajs_uid` is provided as querysting, value of this parameter will populate the `traits` of the `identify` call made.



# [](https://github.com/rudderlabs/rudder-sdk-js/blob/master/README.md#adding-callbacks-to-standard-methods)Adding callbacks to standard methods

One can also define callbacks to common methods of `rudderanalytics` object. _**Note**_: For now, the functionality is supported for `syncPixel` method which is called in Rudder SDK when making sync calls in integrations for relevant destinations.
Expand Down
145 changes: 125 additions & 20 deletions analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
/* eslint-disable no-param-reassign */
import Emitter from "component-emitter";
import after from "after";
import querystring from "component-querystring";
import {
getJSONTrimmed,
generateUUID,
Expand All @@ -35,6 +36,11 @@ import logger from "./utils/logUtil";
import { addDomEventHandlers } from "./utils/autotrack.js";
import ScriptLoader from "./integrations/ScriptLoader";

const queryDefaults = {
trait: "ajs_trait_",
prop: "ajs_prop_",
};

// https://unpkg.com/[email protected]/dist/browser.js

/**
Expand Down Expand Up @@ -355,9 +361,13 @@ class Analytics {
(callback = properties), (options = properties = null);
if (typeof name === "function")
(callback = name), (options = properties = name = null);
if (typeof category === "object")
if (
typeof category === "object" &&
category != null &&
category != undefined
)
(options = name), (properties = category), (name = category = null);
if (typeof name === "object")
if (typeof name === "object" && name != null && name != undefined)
(options = properties), (properties = name), (name = null);
if (typeof category === "string" && typeof name !== "string")
(name = category), (category = null);
Expand Down Expand Up @@ -482,18 +492,18 @@ class Analytics {
*/
processPage(category, name, properties, options, callback) {
const rudderElement = new RudderElementBuilder().setType("page").build();
if (name) {
rudderElement.message.name = name;
}
if (!properties) {
properties = {};
}
if (name) {
rudderElement.message.name = name;
properties.name = name;
}
if (category) {
rudderElement.message.category = category;
properties.category = category;
}
if (properties) {
rudderElement.message.properties = this.getPageProperties(properties); // properties;
}
rudderElement.message.properties = this.getPageProperties(properties); // properties;

this.trackPage(rudderElement, options, callback);
}
Expand Down Expand Up @@ -630,7 +640,7 @@ class Analytics {
}

// assign page properties to context
rudderElement.message.context.page = getDefaultPageProperties();
// rudderElement.message.context.page = getDefaultPageProperties();

rudderElement.message.context.traits = {
...this.userTraits,
Expand All @@ -653,9 +663,7 @@ class Analytics {
}
}

if (options) {
this.processOptionsParam(rudderElement, options);
}
this.processOptionsParam(rudderElement, options);
logger.debug(JSON.stringify(rudderElement));

// structure user supplied integrations object to rudder format
Expand All @@ -674,13 +682,17 @@ class Analytics {
);

// try to first send to all integrations, if list populated from BE
succesfulLoadedIntersectClientSuppliedIntegrations.forEach((obj) => {
if (!obj.isFailed || !obj.isFailed()) {
if (obj[type]) {
obj[type](rudderElement);
try {
succesfulLoadedIntersectClientSuppliedIntegrations.forEach((obj) => {
if (!obj.isFailed || !obj.isFailed()) {
if (obj[type]) {
obj[type](rudderElement);
}
}
}
});
});
} catch (err) {
handleError({ message: `[sendToNative]:${err}` });
}

// config plane native enabled destinations, still not completely loaded
// in the page, add the events to a queue and process later
Expand Down Expand Up @@ -713,6 +725,7 @@ class Analytics {
* @memberof Analytics
*/
processOptionsParam(rudderElement, options) {
const { type, properties } = rudderElement.message;
const toplevelElements = [
"integrations",
"anonymousId",
Expand All @@ -733,18 +746,40 @@ class Analytics {
}
}
}
// assign page properties to context.page
rudderElement.message.context.page =
type == "page"
? this.getContextPageProperties(options, properties)
: this.getContextPageProperties(options);
}

getPageProperties(properties) {
getPageProperties(properties, options) {
const defaultPageProperties = getDefaultPageProperties();
const optionPageProperties = options && options.page ? options.page : {};
for (const key in defaultPageProperties) {
if (properties[key] === undefined) {
properties[key] = defaultPageProperties[key];
properties[key] =
optionPageProperties[key] || defaultPageProperties[key];
}
}
return properties;
}

// Assign page properties to context.page if the same property is not provided under context.page
getContextPageProperties(options, properties) {
const defaultPageProperties = getDefaultPageProperties();
const contextPageProperties = options && options.page ? options.page : {};
for (const key in defaultPageProperties) {
if (contextPageProperties[key] === undefined) {
contextPageProperties[key] =
properties && properties[key]
? properties[key]
: defaultPageProperties[key];
}
}
return contextPageProperties;
}

/**
* Clear user information
*
Expand Down Expand Up @@ -952,6 +987,71 @@ class Analytics {
"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
);
}

/**
* parse the given query string into usable Rudder object
* @param {*} query
*/
parseQueryString(query) {
function getTraitsFromQueryObject(qObj) {
const traits = {};
Object.keys(qObj).forEach((key) => {
if (key.substr(0, queryDefaults.trait.length) == queryDefaults.trait) {
traits[key.substr(queryDefaults.trait.length)] = qObj[key];
}
});

return traits;
}

function getEventPropertiesFromQueryObject(qObj) {
const props = {};
Object.keys(qObj).forEach((key) => {
if (key.substr(0, queryDefaults.prop.length) == queryDefaults.prop) {
props[key.substr(queryDefaults.prop.length)] = qObj[key];
}
});

return props;
}

const returnObj = {};
const queryObject = querystring.parse(query);
const userTraits = getTraitsFromQueryObject(queryObject);
const eventProps = getEventPropertiesFromQueryObject(queryObject);
if (queryObject.ajs_uid) {
returnObj.userId = queryObject.ajs_uid;
returnObj.traits = userTraits;
}
if (queryObject.ajs_aid) {
returnObj.anonymousId = queryObject.ajs_aid;
}
if (queryObject.ajs_event) {
returnObj.event = queryObject.ajs_event;
returnObj.properties = eventProps;
}

return returnObj;
}
}

function pushDataToAnalyticsArray(argumentsArray, obj) {
if (obj.anonymousId) {
if (obj.userId) {
argumentsArray.unshift(
["setAnonymousId", obj.anonymousId],
["identify", obj.userId, obj.traits]
);
} else {
argumentsArray.unshift(["setAnonymousId", obj.anonymousId]);
}
} else if (obj.userId) {
argumentsArray.unshift(["identify", obj.userId, obj.traits]);
}

if (obj.event) {
argumentsArray.push(["track", obj.event, obj.properties]);
}
}

const instance = new Analytics();
Expand Down Expand Up @@ -996,6 +1096,11 @@ if (
argumentsArray.shift();
}

// once loaded, parse querystring of the page url to send events
const parsedQueryObject = instance.parseQueryString(window.location.search);

pushDataToAnalyticsArray(argumentsArray, parsedQueryObject);

if (eventsPushedAlready && argumentsArray && argumentsArray.length > 0) {
for (let i = 0; i < argumentsArray.length; i++) {
instance.toBeProcessedArray.push(argumentsArray[i]);
Expand Down
Loading

0 comments on commit 5239627

Please sign in to comment.