Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@giphy/js-analytics

Package Overview
Dependencies
Maintainers
1
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@giphy/js-analytics - npm Package Compare versions

Comparing version 1.8.0 to 2.0.0-alpha.0

dist/merge-attributes.d.ts

3

dist/index.d.ts

@@ -1,4 +0,3 @@

export { default as mergeAttribute } from './merge-attribute';
export { default as mergeAttributes } from './merge-attributes';
export { default as pingback } from './pingback';
export { addLastSearchResponseId } from './session';
export * from './types';

@@ -16,10 +16,8 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.addLastSearchResponseId = exports.pingback = exports.mergeAttribute = void 0;
var merge_attribute_1 = require("./merge-attribute");
Object.defineProperty(exports, "mergeAttribute", { enumerable: true, get: function () { return __importDefault(merge_attribute_1).default; } });
exports.pingback = exports.mergeAttributes = void 0;
var merge_attributes_1 = require("./merge-attributes");
Object.defineProperty(exports, "mergeAttributes", { enumerable: true, get: function () { return __importDefault(merge_attributes_1).default; } });
var pingback_1 = require("./pingback");
Object.defineProperty(exports, "pingback", { enumerable: true, get: function () { return __importDefault(pingback_1).default; } });
var session_1 = require("./session");
Object.defineProperty(exports, "addLastSearchResponseId", { enumerable: true, get: function () { return session_1.addLastSearchResponseId; } });
__exportStar(require("./types"), exports);
//# sourceMappingURL=index.js.map
import { Pingback } from './types';
declare const pingback: ({ gif, user, responseId, type: pingbackType, actionType, position, attributes }: Pingback) => void;
declare const pingback: ({ gif, userId, eventType, actionType, attributes, queueEvents }: Pingback) => void;
export default pingback;
"use strict";
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var cookie_1 = __importDefault(require("cookie"));
var throttle_debounce_1 = require("throttle-debounce");
var session_1 = require("./session");
var util_1 = require("./util");
var js_util_1 = require("@giphy/js-util");
var uuid_1 = require("uuid"); // v1 only for pingback verfication
var send_pingback_1 = require("./send-pingback");
var queuedPingbacks = {};
var queuedPingbackEvents = [];
/* istanbul ignore next */
var gl = ((typeof window !== 'undefined' ? window : global) || {});
gl.giphyRandomId = '';
var getRandomId = function () {
// it exists in memory
if (!gl.giphyRandomId) {
try {
// it exists in storage
gl.giphyRandomId = localStorage.getItem('giphyRandomId');
}
catch (_) { }
if (!gl.giphyRandomId) {
// we need to create it
gl.giphyRandomId = uuid_1.v1();
try {
// save in storage
localStorage.setItem('giphyRandomId', gl.giphyRandomId);
}
catch (_) { }
}
}
return gl.giphyRandomId;
};
var loggedInUserId = '';
function fetchPingbackRequest() {
js_util_1.forEach(queuedPingbacks, function (actionMap, pingbackType) {
if (actionMap) {
js_util_1.forEach(actionMap, function (action, responseId) {
// if there are no actions lined up inside this pingbackType do nothing
if (action.length) {
var session = session_1.createSession(pingbackType, action, responseId, loggedInUserId);
send_pingback_1.sendPingback(session);
// empty this specific batch
actionMap[responseId] = [];
}
});
}
});
function sendPingbacks() {
var sendEvents = __spreadArrays(queuedPingbackEvents);
queuedPingbackEvents = [];
send_pingback_1.sendPingback(sendEvents);
}
var debouncedPingbackEvent = throttle_debounce_1.debounce(1000, fetchPingbackRequest);
var debouncedPingbackEvent = throttle_debounce_1.debounce(1000, sendPingbacks);
var pingback = function (_a) {
var gif = _a.gif, user = _a.user, responseId = _a.responseId, pingbackType = _a.type, actionType = _a.actionType, position = _a.position, attributes = _a.attributes;
// not all endpoints provide a response_id
if (!responseId) {
js_util_1.Logger.debug("Pingback aborted for " + gif.id + ", no responseId");
return;
var gif = _a.gif, userId = _a.userId, eventType = _a.eventType, actionType = _a.actionType, attributes = _a.attributes, _b = _a.queueEvents, queueEvents = _b === void 0 ? true : _b;
// save the user id for whenever create session is invoked
loggedInUserId = userId ? String(userId) : loggedInUserId;
/* istanbul ignore next */
// get the giphy_pbid cookie
var user_id = cookie_1.default.parse(document ? document.cookie : {}).giphy_pbid;
var newEvent = {
ts: Date.now(),
attributes: attributes,
action_type: actionType,
};
if (loggedInUserId) {
newEvent.logged_in_user_id = loggedInUserId;
}
var id = gif.id, _b = gif.bottle_data, bottle_data = _b === void 0 ? {} : _b;
var tid = bottle_data.tid;
// save the user id for whenever create session is invoked
loggedInUserId = user && user.id ? String(user.id) : loggedInUserId;
// the queue doesn't exist for this pingbackType yet so create it
if (!queuedPingbacks[pingbackType])
queuedPingbacks[pingbackType] = {};
// a map of actions based on pingback type
var actionMap = queuedPingbacks[pingbackType]; // we just created it so ! is ok
// create the searchRepsonseId queue
if (!actionMap[responseId])
actionMap[responseId] = [];
// add the action
actionMap[responseId].push(util_1.getAction(actionType, String(id), tid, position, attributes));
// if there's a tid, skip the queue
tid ? fetchPingbackRequest() : debouncedPingbackEvent();
if (gif) {
if (!gif.analytics_response_payload) {
// abort pingback, analytics_response_payload is required for gif events
return;
}
var gifEvent = newEvent;
gifEvent.analytics_response_payload = gif.analytics_response_payload;
}
if (user_id) {
newEvent.user_id = user_id;
}
else {
newEvent.random_id = getRandomId();
}
if (eventType) {
newEvent.event_type = eventType;
}
queuedPingbackEvents.push(newEvent);
queueEvents ? debouncedPingbackEvent() : sendPingbacks();
};
exports.default = pingback;
//# sourceMappingURL=pingback.js.map

@@ -1,2 +0,2 @@

import { Session } from './session';
export declare const sendPingback: (session: Session) => Promise<Response>;
import { PingbackEvent } from './types';
export declare const sendPingback: (events: PingbackEvent[]) => Promise<Response>;

@@ -6,10 +6,11 @@ "use strict";

// TODO remove api key
var pingBackUrl = 'https://pingback.giphy.com/pingback?apikey=l0HlIwPWyBBUDAUgM';
exports.sendPingback = function (session) {
var pingBackUrl = 'https://pingback.giphy.com/v2/pingback?apikey=l0HlIwPWyBBUDAUgM';
exports.sendPingback = function (events) {
var headers = js_util_1.getGiphySDKRequestHeaders();
/* istanbul ignore next */
headers === null || headers === void 0 ? void 0 : headers.set('Content-Type', 'application/json');
js_util_1.Logger.debug("Pingback session", session);
js_util_1.Logger.debug("Pingback session", events);
return fetch(pingBackUrl, {
method: 'POST',
body: JSON.stringify({ sessions: [session] }),
body: JSON.stringify({ events: events }),
headers: headers,

@@ -16,0 +17,0 @@ });

@@ -1,22 +0,25 @@

import { IGif, IUser, PingbackEventType } from '@giphy/js-types';
export declare type PingbackAttribute = {
key: string;
value: string;
import { IGif, PingbackEventType } from '@giphy/js-types';
export declare type PingbackAttributes = {
[key: string]: string;
};
export declare type Pingback = {
gif: IGif;
user: Partial<IUser>;
type: PingbackEventType;
responseId: string;
gif?: IGif;
userId?: string | number;
eventType?: PingbackEventType;
actionType: PingbackActionType;
position?: ClientRect;
attributes?: PingbackAttribute[];
attributes?: PingbackAttributes;
queueEvents?: boolean;
};
export declare type PingbackActionType = 'CLICK' | 'SEEN' | 'HOVER';
export declare type PingbackRequestAction = {
action_type: PingbackActionType;
export declare type PingbackActionType = 'CLICK' | 'SEEN' | 'HOVER' | 'FAVORITE' | 'SENT';
export declare type PingbackEvent = {
event_type?: PingbackEventType;
user_id?: string;
logged_in_user_id?: string;
action_type: string;
random_id?: string;
attributes: any;
gif_id: string;
tid?: string;
ts: number;
};
export declare type PingbackGifEvent = PingbackEvent & {
analytics_response_payload: string;
};

@@ -11,3 +11,3 @@ {

"name": "@giphy/js-analytics",
"version": "1.8.0",
"version": "2.0.0-alpha.0",
"main": "dist/index.js",

@@ -24,4 +24,4 @@ "types": "dist/index.d.ts",

"dependencies": {
"@giphy/js-types": "^2.1.0",
"@giphy/js-util": "^1.9.2",
"@giphy/js-types": "^3.0.0-alpha.0",
"@giphy/js-util": "^2.0.0-alpha.0",
"@types/uuid": "^8.3.0",

@@ -38,5 +38,5 @@ "append-query": "^2.1.0",

"jest-fetch-mock": "^3.0.3",
"typescript": "^4.0.2"
"typescript": "^4.0.5"
},
"gitHead": "08c96511def29fa490ccc1d506e36e2eeb3c591f"
"gitHead": "d23b0fe639e8e712a6a11140a7fc9922174f71e1"
}
import { IGif, IUser } from '@giphy/js-types'
import fetch from 'jest-fetch-mock'
import pingback from '../pingback'
import { addLastSearchResponseId, SESSION_STORAGE_KEY } from '../session'
const gl = ((typeof window !== 'undefined' ? window : global) || {}) as any
function getRequest(init: RequestInit = {}): { events: [any] } {
return init.body ? JSON.parse(init.body.toString()) : ''
}
describe('pingback', () => {
afterEach(() => {
sessionStorage.clear()
})
const bottle_data = { tid: 'tid!' }
const gif: Partial<IGif> = { id: 9870, bottle_data }
const analytics_response_payload = 'analytics_response_payload gif 9870'
const gif: Partial<IGif> = { id: 9870, analytics_response_payload }
const user: Partial<IUser> = { id: 1234 }
const responseId = 'search response id'
beforeEach(() => {
// @ts-ignore
fetch.resetMocks()
})
test('addLastSearchResponseId', () => {
addLastSearchResponseId('1')
expect(JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEY) as string)).toEqual(['1'])
addLastSearchResponseId('2')
addLastSearchResponseId('2')
expect(JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEY) as string)).toEqual(['1', '2'])
test('no gif, but pingback type', () => {
pingback({
actionType: 'CLICK',
eventType: 'GIF_CHANNEL',
queueEvents: false,
})
expect(fetch.mock.calls.length).toEqual(1)
const [[, options]] = fetch.mock.calls
const {
events: [event],
} = getRequest(options)
delete event.ts
expect(event).toEqual({
action_type: 'CLICK',
event_type: 'GIF_CHANNEL',
random_id: gl.giphyRandomId,
})
})
test('request no user', () => {
test('request user_id', () => {
document.cookie = 'giphy_pbid=1234'
pingback({
gif: gif as IGif,
user: {},
type: 'GIF_RELATED',
responseId,
actionType: 'CLICK',
queueEvents: false,
})
// @ts-ignore
document.cookie = 'giphy_pbid='
expect(fetch.mock.calls.length).toEqual(1)
// @ts-ignore
const [[, options]] = fetch.mock.calls
const {
sessions: [sessionsNoUser],
} = JSON.parse(options.body)
expect(sessionsNoUser.user).toEqual({
logged_in_user_id: '',
random_id: gl.giphyRandomId,
events: [eventNoUser],
} = getRequest(options)
delete eventNoUser.ts
expect(eventNoUser).toEqual({
analytics_response_payload,
action_type: 'CLICK',
user_id: '1234',
// no random id here
})
})
const position = { top: 0, left: 20 } as ClientRect
test('no response id', () => {
test('request no user', () => {
pingback({
gif: gif as IGif,
user,
// @ts-ignore
responseId: undefined,
type: 'GIF_RELATED',
actionType: 'CLICK',
position,
queueEvents: false,
})
// @ts-ignore
expect(fetch.mock.calls.length).toEqual(0)
expect(fetch.mock.calls.length).toEqual(1)
const [[, options]] = fetch.mock.calls
const {
events: [eventNoUser],
} = getRequest(options)
delete eventNoUser.ts
expect(eventNoUser).toEqual({
analytics_response_payload,
action_type: 'CLICK',
random_id: gl.giphyRandomId,
})
})
test('request', () => {
sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(['a', 'b', 'c']))
const attributes = { position: JSON.stringify({ top: 0, left: 20 }) }
pingback({
gif: gif as IGif,
user,
type: 'GIF_RELATED',
responseId,
actionType: 'CLICK',
position,
userId: user?.id,
actionType: 'FAVORITE',
attributes,
queueEvents: false,
})
pingback({
gif: gif as IGif,
user: {},
type: 'GIF_RELATED',
responseId,
actionType: 'CLICK',
actionType: 'SEEN',
queueEvents: false,
})
// @ts-ignore
expect(fetch.mock.calls.length).toEqual(2)
// @ts-ignore
const [[url, options], [, optionsNoUser]] = fetch.mock.calls
const {
sessions: [session],
} = JSON.parse(options.body)
events: [event],
} = getRequest(options)
const {
events: [eventNoUser],
} = getRequest(optionsNoUser)
delete eventNoUser.ts
// remove api key
expect(url).toContain('https://pingback.giphy.com/pingback?apikey=l0HlIwPWyBBUDAUgM')
expect(session.user).toEqual({
expect(url).toContain('https://pingback.giphy.com/v2/pingback?apikey=l0HlIwPWyBBUDAUgM')
delete event.ts
expect(event).toEqual({
action_type: 'FAVORITE',
analytics_response_payload,
logged_in_user_id: String(user.id),
random_id: gl.giphyRandomId,
attributes,
})
const [event] = session.events
const { actions } = event
delete event.actions
expect(event).toEqual({
event_type: 'GIF_RELATED',
referrer: '',
response_id: responseId,
prior_response_id: 'b',
})
const [action] = actions
delete action.ts
expect(action).toEqual({
action_type: 'CLICK',
gif_id: '9870',
tid: 'tid!',
attributes: [
{
key: 'position',
value: JSON.stringify(position),
},
],
})
const {
sessions: [sessionsNoUser],
} = JSON.parse(optionsNoUser.body)
expect(sessionsNoUser.user).toEqual({
expect(eventNoUser).toEqual({
action_type: 'SEEN',
analytics_response_payload,
// but there's still a user bc we save it

@@ -124,37 +120,46 @@ logged_in_user_id: String(user.id),

})
test('no analytics_response_payload should abort', () => {
const testGif = { ...gif } as IGif
testGif.analytics_response_payload = ''
pingback({
gif: testGif,
actionType: 'CLICK',
queueEvents: false,
})
expect(fetch.mock.calls.length).toEqual(0)
})
test('request custom attributes', () => {
sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(['a', 'b', 'c']))
pingback({
gif: gif as IGif,
user: {},
type: 'GIF_RELATED',
responseId,
actionType: 'CLICK',
attributes: [{ key: 'position', value: `1` }],
position,
attributes: { position: `1` },
queueEvents: false,
})
// @ts-ignore
expect(fetch.mock.calls.length).toEqual(1)
// @ts-ignore
const [[, options]] = fetch.mock.calls
const {
sessions: [session],
} = JSON.parse(options.body)
const [event] = session.events
const { actions } = event
delete event.actions
const [action] = actions
delete action.ts
expect(action).toEqual({
events: [event],
} = getRequest(options)
delete event.ts
expect(event).toEqual({
action_type: 'CLICK',
gif_id: '9870',
tid: 'tid!',
attributes: [
{
key: 'position',
value: `1`,
},
],
analytics_response_payload,
logged_in_user_id: String(user.id),
random_id: gl.giphyRandomId,
attributes: { position: `1` },
})
})
test('no call since queueEvents is false', async () => {
pingback({
gif: gif as IGif,
actionType: 'CLICK',
})
expect(fetch.mock.calls.length).toEqual(0)
await new Promise((resolve) => {
setTimeout(() => resolve(), 1110)
})
expect(fetch.mock.calls.length).toEqual(1)
})
})

@@ -1,4 +0,3 @@

export { default as mergeAttribute } from './merge-attribute'
export { default as mergeAttributes } from './merge-attributes'
export { default as pingback } from './pingback'
export { addLastSearchResponseId } from './session'
export * from './types'

@@ -0,61 +1,84 @@

import cookie from 'cookie'
import { debounce } from 'throttle-debounce'
import { createSession } from './session'
import { Pingback, PingbackRequestAction } from './types'
import { getAction } from './util'
import { PingbackEventType } from '@giphy/js-types'
import { forEach, Logger } from '@giphy/js-util'
import { v1 as uuid } from 'uuid' // v1 only for pingback verfication
import { sendPingback } from './send-pingback'
import { Pingback, PingbackEvent, PingbackGifEvent } from './types'
type ActionMap = { [key: string]: PingbackRequestAction[] }
let queuedPingbackEvents: PingbackEvent[] = []
const queuedPingbacks: { [key in PingbackEventType]?: ActionMap } = {}
/* istanbul ignore next */
const gl = ((typeof window !== 'undefined' ? window : global) || {}) as any
gl.giphyRandomId = ''
const getRandomId = () => {
// it exists in memory
if (!gl.giphyRandomId) {
try {
// it exists in storage
gl.giphyRandomId = localStorage.getItem('giphyRandomId')
} catch (_) {}
if (!gl.giphyRandomId) {
// we need to create it
gl.giphyRandomId = uuid()
try {
// save in storage
localStorage.setItem('giphyRandomId', gl.giphyRandomId)
} catch (_) {}
}
}
return gl.giphyRandomId
}
let loggedInUserId = ''
function fetchPingbackRequest() {
forEach(queuedPingbacks, (actionMap: ActionMap, pingbackType: PingbackEventType) => {
if (actionMap) {
forEach(actionMap, (action: PingbackRequestAction[], responseId: string) => {
// if there are no actions lined up inside this pingbackType do nothing
if (action.length) {
const session = createSession(pingbackType, action, responseId, loggedInUserId)
sendPingback(session)
// empty this specific batch
actionMap[responseId] = []
}
})
}
})
function sendPingbacks() {
const sendEvents = [...queuedPingbackEvents]
queuedPingbackEvents = []
sendPingback(sendEvents)
}
const debouncedPingbackEvent = debounce(1000, fetchPingbackRequest)
const debouncedPingbackEvent = debounce(1000, sendPingbacks)
const pingback = ({ gif, user, responseId, type: pingbackType, actionType, position, attributes }: Pingback) => {
// not all endpoints provide a response_id
if (!responseId) {
Logger.debug(`Pingback aborted for ${gif.id}, no responseId`)
return
const pingback = ({ gif, userId, eventType, actionType, attributes, queueEvents = true }: Pingback) => {
// save the user id for whenever create session is invoked
loggedInUserId = userId ? String(userId) : loggedInUserId
/* istanbul ignore next */
// get the giphy_pbid cookie
const user_id = cookie.parse(document ? document.cookie : ({} as any)).giphy_pbid
const newEvent: PingbackEvent = {
ts: Date.now(),
attributes,
action_type: actionType,
}
const { id, bottle_data = {} } = gif
const { tid } = bottle_data
// save the user id for whenever create session is invoked
loggedInUserId = user && user.id ? String(user.id) : loggedInUserId
if (loggedInUserId) {
newEvent.logged_in_user_id = loggedInUserId
}
// the queue doesn't exist for this pingbackType yet so create it
if (!queuedPingbacks[pingbackType]) queuedPingbacks[pingbackType] = {}
if (gif) {
if (!gif.analytics_response_payload) {
// abort pingback, analytics_response_payload is required for gif events
return
}
const gifEvent = newEvent as PingbackGifEvent
gifEvent.analytics_response_payload = gif.analytics_response_payload
}
// a map of actions based on pingback type
const actionMap = queuedPingbacks[pingbackType]! // we just created it so ! is ok
if (user_id) {
newEvent.user_id = user_id
} else {
newEvent.random_id = getRandomId()
}
// create the searchRepsonseId queue
if (!actionMap[responseId]) actionMap[responseId] = []
if (eventType) {
newEvent.event_type = eventType
}
// add the action
actionMap[responseId].push(getAction(actionType, String(id), tid, position, attributes))
queuedPingbackEvents.push(newEvent)
// if there's a tid, skip the queue
tid ? fetchPingbackRequest() : debouncedPingbackEvent()
queueEvents ? debouncedPingbackEvent() : sendPingbacks()
}
export default pingback
import { getGiphySDKRequestHeaders, Logger } from '@giphy/js-util'
import { Session } from './session'
import { PingbackEvent } from './types'
// TODO remove api key
const pingBackUrl = 'https://pingback.giphy.com/pingback?apikey=l0HlIwPWyBBUDAUgM'
const pingBackUrl = 'https://pingback.giphy.com/v2/pingback?apikey=l0HlIwPWyBBUDAUgM'
export const sendPingback = (session: Session) => {
export const sendPingback = (events: PingbackEvent[]) => {
const headers = getGiphySDKRequestHeaders()
/* istanbul ignore next */
headers?.set('Content-Type', 'application/json')
Logger.debug(`Pingback session`, session)
Logger.debug(`Pingback session`, events)
return fetch(pingBackUrl, {
method: 'POST',
body: JSON.stringify({ sessions: [session] }),
body: JSON.stringify({ events }),
headers,
})
}

@@ -1,26 +0,29 @@

import { IGif, IUser, PingbackEventType } from '@giphy/js-types'
import { IGif, PingbackEventType } from '@giphy/js-types'
export type PingbackAttribute = {
key: string
value: string
}
export type PingbackAttributes = { [key: string]: string }
export type Pingback = {
gif: IGif
user: Partial<IUser>
type: PingbackEventType
responseId: string
// for pingbacks with GIFs
gif?: IGif
userId?: string | number
eventType?: PingbackEventType
actionType: PingbackActionType
position?: ClientRect
attributes?: PingbackAttribute[]
attributes?: PingbackAttributes
queueEvents?: boolean
}
export type PingbackActionType = 'CLICK' | 'SEEN' | 'HOVER'
export type PingbackActionType = 'CLICK' | 'SEEN' | 'HOVER' | 'FAVORITE' | 'SENT'
export type PingbackRequestAction = {
action_type: PingbackActionType
export type PingbackEvent = {
event_type?: PingbackEventType
user_id?: string
logged_in_user_id?: string
action_type: string
random_id?: string
attributes: any
gif_id: string
tid?: string
ts: number
}
export type PingbackGifEvent = PingbackEvent & {
analytics_response_payload: string
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc