-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement fingerprinting capture for deferred deep linking (#40)
* Add initial impl of fp capture and record * Wire up click fp capture upon user accept action tap * Rewire trigger support for ddl banner * Update bundles * Update fp catpure page url * Reset host page body styles on unmount * Prevent double load state firing in ddl mgr * Refactor prompt activation to prevent race preventing initial display of banner * Update bundles * Remove redundant suppression check * Update version * Ensure iframe message is from expected origin * Remove unused imports * Enhance ui action redirection handling to store/deeplink * Update and alter strategy for requesting fp * Encapsulate fp readiness in component * Remove await/req resolution in helper fn * Uprev package and bundles Co-authored-by: Rob Dick <r.dick@kumulos.com>
- Loading branch information
Showing
24 changed files
with
488 additions
and
58 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { Component, h, createRef, RefObject } from 'preact'; | ||
import { createPortal } from 'preact/compat'; | ||
import { | ||
ClientMessageType, | ||
HostMessage, | ||
HostMessageType, | ||
FingerprintComponents | ||
} from './types'; | ||
import { FP_CAPTURE_URL } from '../core'; | ||
|
||
enum CaptureState { | ||
IDLE, | ||
CAPTURING | ||
} | ||
|
||
interface FpCaptureProps { | ||
onCaptured: (components: FingerprintComponents) => void; | ||
} | ||
|
||
interface FpCaptureState { | ||
isReady: boolean; | ||
captureState: CaptureState; | ||
} | ||
|
||
export default class FpCapture extends Component< | ||
FpCaptureProps, | ||
FpCaptureState | ||
> { | ||
private iFrameRef: RefObject<HTMLIFrameElement>; | ||
|
||
constructor(props: FpCaptureProps) { | ||
super(props); | ||
|
||
this.iFrameRef = createRef<HTMLIFrameElement>(); | ||
|
||
this.state = { | ||
isReady: false, | ||
captureState: CaptureState.IDLE | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
window.addEventListener('message', this.onMessage); | ||
} | ||
|
||
componentWillUnmount() { | ||
window.removeEventListener('message', this.onMessage); | ||
} | ||
|
||
componentWillUpdate(_: FpCaptureProps, nextState: FpCaptureState) { | ||
const { isReady, captureState } = nextState; | ||
const prevCaptureState = this.state.captureState; | ||
|
||
if ( | ||
isReady && | ||
captureState === CaptureState.CAPTURING && | ||
prevCaptureState === CaptureState.IDLE | ||
) { | ||
this.dispatchMessage({ | ||
type: HostMessageType.REQUEST_FINGERPRINT | ||
}); | ||
} | ||
} | ||
|
||
public requestFp() { | ||
console.info(`FpCapure: requesting fp capture`); | ||
|
||
if (this.state.captureState !== CaptureState.IDLE) { | ||
console.error('FpCapture.requestFp: captureState not IDLE'); | ||
return; | ||
} | ||
|
||
this.setState({ captureState: CaptureState.CAPTURING }); | ||
} | ||
|
||
private onMessage = (e: MessageEvent) => { | ||
console.info( | ||
`FpCapure: message ${e.data.type} received from ${e.origin}` | ||
); | ||
|
||
const message = e.data; | ||
|
||
if (e.origin !== FP_CAPTURE_URL) { | ||
return; | ||
} | ||
|
||
switch (message.type) { | ||
case ClientMessageType.READY: | ||
this.setState({ isReady: true }); | ||
break; | ||
case ClientMessageType.FINGERPRINT_GENERATED: | ||
this.setState({ captureState: CaptureState.IDLE }, () => { | ||
this.props.onCaptured(message.data.components); | ||
}); | ||
break; | ||
} | ||
}; | ||
|
||
private dispatchMessage = (message: HostMessage) => { | ||
console.info( | ||
`FpCapure: dispatching ${message.type} message to capture frame` | ||
); | ||
|
||
const window = this.iFrameRef.current?.contentWindow; | ||
|
||
if (!window) { | ||
return; | ||
} | ||
|
||
window.postMessage(message, FP_CAPTURE_URL); | ||
}; | ||
|
||
render() { | ||
return createPortal( | ||
<iframe | ||
ref={this.iFrameRef} | ||
src={FP_CAPTURE_URL} | ||
style={{ width: 0, height: 0 }} | ||
/>, | ||
document.body | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { DDL_BASE_URL, Context, getInstallId } from '../core'; | ||
import { authedFetch } from '../core/utils'; | ||
import { FingerprintComponents } from './types'; | ||
|
||
export async function sendClickRequest( | ||
ctx: Context, | ||
bannerUid: string, | ||
fingerprint: FingerprintComponents | ||
): Promise<Response> { | ||
const url = `${DDL_BASE_URL}/v1/banners/${bannerUid}/taps`; | ||
const webInstallId = await getInstallId(); | ||
|
||
return authedFetch(ctx, url, { | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
webInstallId, | ||
fingerprint | ||
}) | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
|
||
type Message<T, D = never> = | ||
| { | ||
type: T; | ||
} | ||
| { type: T; data: D }; | ||
|
||
export enum HostMessageType { | ||
REQUEST_FINGERPRINT = 'REQUEST_FINGERPRINT', | ||
} | ||
|
||
export enum ClientMessageType { | ||
READY = 'READY', | ||
FINGERPRINT_GENERATED = 'FINGERPRINT_GENERATED', | ||
} | ||
|
||
export type FingerprintComponents = Record<string, string>; | ||
|
||
export type HostMessage = Message<HostMessageType.REQUEST_FINGERPRINT>; | ||
|
||
export type ClientMessage = | ||
| Message<ClientMessageType.READY> | ||
| Message< | ||
ClientMessageType.FINGERPRINT_GENERATED, | ||
{ components: FingerprintComponents } | ||
>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.