2026-02-13 07:35:14 +00:00
import { addQueryId } from "./_addQueryId" ;
2024-01-05 12:14:38 +00:00
import type AlgoliaAnalytics from "./insights" ;
import type { InsightsAdditionalEventParams , InsightsEvent } from "./types" ;
2026-02-13 07:35:14 +00:00
import { isPromise , isUndefined , removeQueryForObjects } from "./utils" ;
2024-01-05 12:14:38 +00:00
import type { RequestFnType } from "./utils/request" ;
export function makeSendEvents ( requestFn : RequestFnType ) {
return function sendEvents (
this : AlgoliaAnalytics ,
eventData : InsightsEvent [ ] ,
additionalParams? : InsightsAdditionalEventParams
2026-02-13 07:35:14 +00:00
) : Promise < boolean > {
2024-01-05 12:14:38 +00:00
if ( this . _userHasOptedOut ) {
2026-02-13 07:35:14 +00:00
return Promise . resolve ( false ) ;
2024-01-05 12:14:38 +00:00
}
const hasCredentials =
( ! isUndefined ( this . _apiKey ) && ! isUndefined ( this . _appId ) ) ||
( additionalParams ? . headers ? . [ "X-Algolia-Application-Id" ] &&
additionalParams ? . headers ? . [ "X-Algolia-API-Key" ] ) ;
if ( ! hasCredentials ) {
throw new Error (
"Before calling any methods on the analytics, you first need to call the 'init' function with appId and apiKey parameters or provide custom credentials in additional parameters."
) ;
}
if ( ! this . _userToken && this . _anonymousUserToken ) {
this . setAnonymousUserToken ( true ) ;
}
2026-02-13 07:35:14 +00:00
const events : InsightsEvent [ ] = (
additionalParams ? . inferQueryID ? addQueryId ( eventData ) : eventData
) . map ( ( data ) = > {
2024-01-05 12:14:38 +00:00
const { filters , . . . rest } = data ;
const payload : InsightsEvent = {
. . . rest ,
userToken : data?.userToken ? ? this . _userToken ,
authenticatedUserToken :
data ? . authenticatedUserToken ? ? this . _authenticatedUserToken
} ;
if ( ! isUndefined ( filters ) ) {
payload . filters = filters . map ( encodeURIComponent ) ;
}
return payload ;
} ) ;
2026-02-13 07:35:14 +00:00
if ( events . length === 0 ) {
return Promise . resolve ( false ) ;
}
const send = sendRequest (
2024-01-05 12:14:38 +00:00
requestFn ,
this . _ua ,
this . _endpointOrigin ,
events ,
this . _appId ,
this . _apiKey ,
additionalParams ? . headers
) ;
2026-02-13 07:35:14 +00:00
return isPromise ( send ) ? send . then ( purgePurchased ( events ) ) : send ;
} ;
}
function purgePurchased ( events : InsightsEvent [ ] ) : ( value : boolean ) = > boolean {
return ( sent ) = > {
if ( sent ) {
events
. filter (
( { eventType , eventSubtype , objectIDs } ) = >
eventType === "conversion" &&
eventSubtype === "purchase" &&
objectIDs ? . length
)
. forEach ( ( { index , objectIDs } ) = >
removeQueryForObjects ( index , objectIDs ! )
) ;
}
return sent ;
2024-01-05 12:14:38 +00:00
} ;
}
// eslint-disable-next-line max-params
function sendRequest (
requestFn : RequestFnType ,
userAgents : string [ ] ,
endpointOrigin : string ,
events : InsightsEvent [ ] ,
appId? : string ,
apiKey? : string ,
additionalHeaders : InsightsAdditionalEventParams [ "headers" ] = { }
) : Promise < boolean > {
const {
"X-Algolia-Application-Id" : providedAppId ,
"X-Algolia-API-Key" : providedApiKey ,
. . . restHeaders
} = additionalHeaders ;
// Auth query
const headers : Record < string , string > = {
"X-Algolia-Application-Id" : providedAppId ? ? appId ,
"X-Algolia-API-Key" : providedApiKey ? ? apiKey ,
"X-Algolia-Agent" : encodeURIComponent ( userAgents . join ( "; " ) ) ,
. . . restHeaders
} ;
const queryParameters = Object . keys ( headers )
. map ( ( key ) = > ` ${ key } = ${ headers [ key ] } ` )
. join ( "&" ) ;
const reportingURL = ` ${ endpointOrigin } /1/events? ${ queryParameters } ` ;
return requestFn ( reportingURL , { events } ) ;
}