Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more interface for flutter web support #444

Merged
merged 8 commits into from
Nov 17, 2021
229 changes: 223 additions & 6 deletions src/amplitude-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import base64Id from './base64Id';
import DEFAULT_OPTIONS from './options';
import getHost from './get-host';
import baseCookie from './base-cookie';
import { getEventLogApi } from './server-zone';
import { AmplitudeServerZone, getEventLogApi } from './server-zone';
import ConfigManager from './config-manager';

/**
Expand Down Expand Up @@ -858,15 +858,33 @@ AmplitudeClient.prototype.setDomain = function setDomain(domain) {
* Sets an identifier for the current user.
* @public
* @param {string} userId - identifier to set. Can be null.
* @param {boolean} startNewSession - (optional) if start a new session or not
* @example amplitudeClient.setUserId('[email protected]');
*/
AmplitudeClient.prototype.setUserId = function setUserId(userId) {
AmplitudeClient.prototype.setUserId = function setUserId(userId, startNewSession = false) {
if (!utils.validateInput(startNewSession, 'startNewSession', 'boolean')) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setUserId'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.userId = (userId !== undefined && userId !== null && '' + userId) || null;
if (startNewSession) {
if (this.options.unsetParamsReferrerOnNewSession) {
this._unsetUTMParams();
}
this._newSession = true;
this._sessionId = new Date().getTime();

// only capture UTM params and referrer if new session
if (this.options.saveParamsReferrerOncePerSession) {
this._trackParamsAndReferrer();
}
}

_saveCookieData(this);
} catch (e) {
utils.log.error(e);
Expand Down Expand Up @@ -1232,6 +1250,7 @@ AmplitudeClient.prototype._logEvent = function _logEvent(
timestamp,
callback,
errorCallback,
outOfSession,
) {
_loadCookieData(this); // reload cookie before each log event to sync event meta-data between windows and tabs

Expand All @@ -1257,7 +1276,13 @@ AmplitudeClient.prototype._logEvent = function _logEvent(
}
var sequenceNumber = this.nextSequenceNumber();
var eventTime = type(timestamp) === 'number' ? timestamp : new Date().getTime();
if (!this._sessionId || !this._lastEventTime || eventTime - this._lastEventTime > this.options.sessionTimeout) {
if (outOfSession) {
this._sessionId = -1;
} else if (
!this._sessionId ||
!this._lastEventTime ||
eventTime - this._lastEventTime > this.options.sessionTimeout
) {
this._sessionId = eventTime;
}
this._lastEventTime = eventTime;
Expand Down Expand Up @@ -1383,13 +1408,20 @@ AmplitudeClient.prototype._limitEventsQueued = function _limitEventsQueued(queue
* @param {Amplitude~eventCallback} opt_error_callback - (optional) a callback function to run after the event logging
* fails. The failure can be from the request being malformed or from a network failure
* Note: the server response code and response body from the event upload are passed to the callback function.
* @param {boolean} outOfSession - (optional) if this event is out of session or not
* @example amplitudeClient.logEvent('Clicked Homepage Button', {'finished_flow': false, 'clicks': 15});
*/
AmplitudeClient.prototype.logEvent = function logEvent(eventType, eventProperties, opt_callback, opt_error_callback) {
AmplitudeClient.prototype.logEvent = function logEvent(
eventType,
eventProperties,
opt_callback,
opt_error_callback,
outOfSession = false,
) {
if (this._shouldDeferCall()) {
return this._q.push(['logEvent'].concat(Array.prototype.slice.call(arguments, 0)));
}
return this.logEventWithTimestamp(eventType, eventProperties, null, opt_callback, opt_error_callback);
return this.logEventWithTimestamp(eventType, eventProperties, null, opt_callback, opt_error_callback, outOfSession);
};

/**
Expand All @@ -1403,6 +1435,7 @@ AmplitudeClient.prototype.logEvent = function logEvent(eventType, eventPropertie
* @param {Amplitude~eventCallback} opt_error_callback - (optional) a callback function to run after the event logging
* fails. The failure can be from the request being malformed or from a network failure
* Note: the server response code and response body from the event upload are passed to the callback function.
* @param {boolean} outOfSession - (optional) if out of the sessioin or not
* @example amplitudeClient.logEvent('Clicked Homepage Button', {'finished_flow': false, 'clicks': 15});
*/
AmplitudeClient.prototype.logEventWithTimestamp = function logEvent(
Expand All @@ -1411,6 +1444,7 @@ AmplitudeClient.prototype.logEventWithTimestamp = function logEvent(
timestamp,
opt_callback,
opt_error_callback,
outOfSession = false,
) {
if (this._shouldDeferCall()) {
return this._q.push(['logEventWithTimestamp'].concat(Array.prototype.slice.call(arguments, 0)));
Expand All @@ -1435,6 +1469,13 @@ AmplitudeClient.prototype.logEventWithTimestamp = function logEvent(
});
return -1;
}

if (!utils.validateInput(outOfSession, 'outOfSession', 'boolean')) {
_logErrorsWithCallbacks(opt_callback, opt_error_callback, 0, 'No request sent', {
reason: 'Invalid outOfSession value',
});
}

return this._logEvent(
eventType,
eventProperties,
Expand All @@ -1445,6 +1486,7 @@ AmplitudeClient.prototype.logEventWithTimestamp = function logEvent(
timestamp,
opt_callback,
opt_error_callback,
outOfSession,
);
};

Expand Down Expand Up @@ -1473,6 +1515,7 @@ AmplitudeClient.prototype.logEventWithGroups = function (
groups,
opt_callback,
opt_error_callback,
outOfSession = false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this one in group also used in flutter? Or used in other SDK?

Copy link
Contributor Author

@yuhao900914 yuhao900914 Nov 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flutter doesn't have the logEventWithGroups method. But I think those functions are exposed to Amplitude-Javascript user, so it's better to keep them consistent. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yuhao900914 For other SDKs we have, do we have similaroutOfSession support on logEventWithGroups?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andorid and iOS are similar, the logEvent function is able to pass groups info and outOfSession together.
- (void)logEvent:(NSString *)eventType withEventProperties:(NSDictionary *)eventProperties withApiProperties:(NSDictionary *)apiProperties withUserProperties:(NSDictionary *)userProperties withGroups:(NSDictionary *)groups withGroupProperties:(NSDictionary *)groupProperties withTimestamp:(NSNumber *)timestamp outOfSession:(BOOL)outOfSession {xxx}

) {
if (this._shouldDeferCall()) {
return this._q.push(['logEventWithGroups'].concat(Array.prototype.slice.call(arguments, 0)));
Expand All @@ -1490,7 +1533,25 @@ AmplitudeClient.prototype.logEventWithGroups = function (
});
return -1;
}
return this._logEvent(eventType, eventProperties, null, null, groups, null, null, opt_callback, opt_error_callback);

if (!utils.validateInput(outOfSession, 'outOfSession', 'boolean')) {
_logErrorsWithCallbacks(event.callback, event.errorCallback, 0, 'No request sent', {
reason: 'Invalid outOfSession value',
});
}

return this._logEvent(
eventType,
eventProperties,
null,
null,
groups,
null,
null,
opt_callback,
opt_error_callback,
outOfSession,
);
};

/**
Expand Down Expand Up @@ -1851,6 +1912,26 @@ AmplitudeClient.prototype.setLibrary = function setLibrary(name, version) {
this.options.library = { name: name, version: version };
};

/**
* Sets the library name.
* @public
* @param {string} libraryName - the library name.
* @example amplitudeClient.setLibraryName('my_library_name');
*/
AmplitudeClient.prototype.setLibraryName = function setLibraryName(libraryName) {
this.options.library.name = libraryName;
yuhao900914 marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* Sets the library Version.
* @public
* @param {string} userId - the library version.
* @example amplitudeClient.setLibraryVersion('1.0.0');
*/
AmplitudeClient.prototype.setLibraryVersion = function setLibraryVersion(libraryVersion) {
this.options.library.version = libraryVersion;
yuhao900914 marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* Determines whether or not to push call to this._q or invoke it
* @private
Expand Down Expand Up @@ -1897,4 +1978,140 @@ AmplitudeClient.prototype._refreshDynamicConfig = function _refreshDynamicConfig
}
};

/**
* Returns the deviceId value.
* @public
* @return {string} Id of current device.
*/
AmplitudeClient.prototype.getDeviceId = function getDeviceId() {
return this.options.deviceId;
};

/**
* Returns the userId.
* @public
* @return {string} Id of current user.
*/
AmplitudeClient.prototype.getUserId = function getUserId() {
return this.options.userId;
};

/**
* Set a custom session expiration time.
* @public
* @param {number} timeInMillis - session expireation time in milliseconds.
*/
AmplitudeClient.prototype.setMinTimeBetweenSessionsMillis = function setMinTimeBetweenSessionsMillis(timeInMillis) {
if (!utils.validateInput(timeInMillis, 'timeInMillis', 'number')) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setMinTimeBetweenSessionsMillis'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.sessionTimeout = timeInMillis;
} catch (e) {
utils.log.error(e);
}
};

/**
* Sets minimum number of events to batch together per request if batchEvents is true.
* @public
* @param {number} eventUploadThreshold - The number of the event upload threshold. Default value is 30.
* @example amplitudeClient.setEventUploadThreshold(10);
*/
AmplitudeClient.prototype.setEventUploadThreshold = function setEventUploadThreshold(eventUploadThreshold) {
if (!utils.validateInput(eventUploadThreshold, 'eventUploadThreshold', 'number')) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setEventUploadThreshold'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.eventUploadThreshold = eventUploadThreshold;
} catch (e) {
utils.log.error(e);
}
};

/**
* Dynamically adjust server URL
* @public
* @param {bool} useDynamicConfig - if enable dynamic config or not.
* @example amplitudeClient.setUseDynamicConfig(true);
*/
AmplitudeClient.prototype.setUseDynamicConfig = function setUseDynamicConfig(useDynamicConfig) {
if (!utils.validateInput(useDynamicConfig, 'useDynamicConfig', 'boolean')) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setUseDynamicConfig'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.useDynamicConfig = useDynamicConfig;
this._refreshDynamicConfig();
} catch (e) {
utils.log.error(e);
}
};

/**
* Sets the server zone , used for server api endpoint and dynamic configuration..
yuhao900914 marked this conversation as resolved.
Show resolved Hide resolved
* @public
* @param {string} serverZone - the server zone value. AmplitudeServerZone.US or AmplitudeServerZone.EU.
* @param {bool} serverZoneBasedApi - (optional) update api endpoint with serverZone change or not. For data residency, recommend to enable it unless using own proxy server.
* @example amplitudeClient.setServerZone('[email protected]', true);
*/
AmplitudeClient.prototype.setServerZone = function setServerZone(serverZone, serverZoneBasedApi = true) {
if (
(serverZone !== AmplitudeServerZone.EU && serverZone !== AmplitudeServerZone.US) ||
!utils.validateInput(serverZoneBasedApi, 'serverZoneBasedApi', 'boolean')
) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setServerZone'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.serverZone = serverZone;
this.options.serverZoneBasedApi = serverZoneBasedApi;
if (serverZoneBasedApi) {
this.options.apiEndpoint = getEventLogApi(this.options.serverZone);
}
} catch (e) {
utils.log.error(e);
}
};

/**
* Sets the server URL for the request.
* @public
* @param {string} serverUrl - The value of the server URL.
* @example amplitudeClient.setServerUrl('api.amplitude.com');
*/
AmplitudeClient.prototype.setServerUrl = function setServerUrl(serverUrl) {
if (!utils.validateInput(serverUrl, 'serverUrl', 'string')) {
return;
}

if (this._shouldDeferCall()) {
return this._q.push(['setServerUrl'].concat(Array.prototype.slice.call(arguments, 0)));
}

try {
this.options.apiEndpoint = serverUrl;
} catch (e) {
utils.log.error(e);
}
};

export default AmplitudeClient;
Loading