Skip to content

Commit

Permalink
Make storage keys configurable (#6)
Browse files Browse the repository at this point in the history
People should be able to control how the localStorage is accessed on their site

Also:
* Remove outdated comment
* Update changelog
* Update package.json
  • Loading branch information
JeroenBakker authored Aug 2, 2023
1 parent 4fcc03e commit bd1e9eb
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 14 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ Implemented this release automation: https://superface.ai/blog/npm-publish-gh-ac
- GitHub action to publish new versions to npm.
- Automatically move unreleased changed to a new release section in the changelog.

## [0.3.2] - 2023-08-02

### Added

- Settings for storage keys, the defaults are the same as before.

## [0.3.1] - 2023-08-01

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jeroen.bakker/just-attribute",
"version": "0.3.1",
"version": "0.3.2",
"description": "Realtime privacy-conscious marketing attribution for the web",
"author": "Jeroen Bakker",
"license": "MIT",
Expand Down
29 changes: 16 additions & 13 deletions src/InteractionLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,17 @@ interface LoggerSettings {
* Whenever the log is modified all interactions that are older will be removed.
*/
logRetentionTime: number;
};
/**
* The key that the interaction log is stored under
*/
logStorageKey: string;
/**
* The key that the last interaction timestamp is stored under
*/
lastInteractionStorageKey: string;
}

export default class InteractionLogger {
private static readonly logStorageKey = 'ja_interaction_log';
private static readonly lastInteractionTimestampStorageKey = 'ja_last_interaction';
private static readonly queryMapping: Record<string, string> = {
utm_campaign: 'campaign',
utm_content: 'content',
Expand All @@ -54,13 +60,10 @@ export default class InteractionLogger {
sessionTimeout: InteractionLogger.MINUTE * 30,
logLimit: 100,
logRetentionTime: InteractionLogger.DAY * 30,
logStorageKey: 'ja_interaction_log',
lastInteractionStorageKey: 'ja_last_interaction',
};

/**
* @param sessionTimeout How long it takes for a session to end after inactivity, in milliseconds.
* The first interaction of a session will always be logged and can be attributed, even if it's direct.
* Defaults to 30 minutes.
*/
public constructor(
settings: Partial<LoggerSettings> = {},
) {
Expand Down Expand Up @@ -175,7 +178,7 @@ export default class InteractionLogger {
}

public interactionLog(): Interaction[] {
const jsonLog = this.settings.storage.getItem(InteractionLogger.logStorageKey);
const jsonLog = this.settings.storage.getItem(this.settings.logStorageKey);

if (! jsonLog) {
return [];
Expand All @@ -193,7 +196,7 @@ export default class InteractionLogger {
* This could be used after a user has converted and the attribution has been determined.
*/
public clearLog(): void {
this.settings.storage.setItem(InteractionLogger.logStorageKey, null);
this.settings.storage.setItem(this.settings.logStorageKey, null);
}

public lastInteraction(): Interaction|null {
Expand Down Expand Up @@ -256,13 +259,13 @@ export default class InteractionLogger {
*/
private logLastInteractionTimestamp(timestamp: number): void {
this.settings.storage.setItem(
InteractionLogger.lastInteractionTimestampStorageKey,
this.settings.lastInteractionStorageKey,
String(timestamp),
);
}

private lastInteractionTimestamp(): number|null {
const timestampString = this.settings.storage.getItem(InteractionLogger.lastInteractionTimestampStorageKey);
const timestampString = this.settings.storage.getItem(this.settings.lastInteractionStorageKey);
if (! timestampString) {
return null;
}
Expand All @@ -289,6 +292,6 @@ export default class InteractionLogger {
log = log.slice(-this.settings.logLimit);
}

this.settings.storage.setItem(InteractionLogger.logStorageKey, JSON.stringify(log));
this.settings.storage.setItem(this.settings.logStorageKey, JSON.stringify(log));
}
}
19 changes: 19 additions & 0 deletions tests/InteractionLogger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,22 @@ test('it handles an older log that is too large', async () => {
{source: 'foo', medium: '4', timestamp: 4},
]);
});

test('the log storage key can be set', async () => {
const storage = new MemoryStorage();
const logger = new InteractionLogger({storage, logStorageKey: 'foo'});

const interaction = {source: 'foo', medium: 'bar', timestamp: 1};
logger.processInteraction(interaction);

expect(storage.getItem('foo')).toEqual(JSON.stringify([interaction]));
});

test('the last interaction storage key can be set', async () => {
const storage = new MemoryStorage();
const logger = new InteractionLogger({storage, lastInteractionStorageKey: 'foo'});

logger.processInteraction({source: 'foo', medium: 'bar', timestamp: 1});

expect(storage.getItem('foo')).toBe('1');
});

0 comments on commit bd1e9eb

Please sign in to comment.