Skip to content

Commit

Permalink
Merge pull request #11 from adjust/v101
Browse files Browse the repository at this point in the history
Version 1.0.1
  • Loading branch information
YaraMatkova authored Dec 5, 2023
2 parents 74895a3 + e1c0710 commit 7840b4a
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 26 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ coverage/
dist/

sdk/README.md
sdk/CHANGELOG.md
sdk/LICENSE
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
### Version 1.0.1 (5th December 2023)

#### Fixed
- Fixed issue with invalid URL generated when search query containing question mark ('?') was passed as an iOS deeplink path.

---

### Version 1.0.0 (23rd November 2023)

The first release of a new Adjust Smart Banner SDK!
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ To <a id="loading-snippet">load Smart Banner SDK through CDN</a> paste the follo
</script>
```

When loading the sdk through CDN we suggest using minified version. You can target specific version like `https://cdn.adjust.com/adjust-smart-banner-1.0.0.min.js`, or you can target latest version `https://cdn.adjust.com/adjust-smart-banner-latest.min.js` if you want automatic updates without need to change the target file. The sdk files are cached so they are served as fast as possible, and the cache is refreshed every half an hour. If you want updates immediately make sure to target specific version.
When loading the sdk through CDN we suggest using minified version. You can target specific version like `https://cdn.adjust.com/adjust-smart-banner-1.0.1.min.js`, or you can target latest version `https://cdn.adjust.com/adjust-smart-banner-latest.min.js` if you want automatic updates without need to change the target file. The sdk files are cached so they are served as fast as possible, and the cache is refreshed every half an hour. If you want updates immediately make sure to target specific version.


## <a id="initialization">Initialization</a>
Expand Down
2 changes: 1 addition & 1 deletion demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@adjustcom/smart-banner-sdk": "^1.0.0",
"@adjustcom/smart-banner-sdk": "^1.0.1",
"lorem-ipsum": "^2.0.8"
},
"author": "Adjust GmbH",
Expand Down
8 changes: 4 additions & 4 deletions demo/src/data/default-sdk-settings.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { InitialisationOptions } from '@adjustcom/smart-banner-sdk';

export const defaultSdkSettings: InitialisationOptions = {
appToken: '6uzo4j2d8hz4',
appToken: {
ios: '36wbd8gmlvsw',
android: 'mgznt27qbaio'
},
logLevel: 'verbose',
iosDeepLinkPath: 'items/{product}',
androidDeepLinkPath: '{path}',
context: { promo: 'kitty', product: 't-shirt', path: 'android/{promo}-promo' }
};
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adjustcom/smart-banner-sdk-project",
"version": "1.0.0",
"version": "1.0.1",
"description": "Adjust Smart Banner SDK",
"scripts": {
"build": "npm run build --workspace=layout && npm run build --workspace=sdk && npm run build:snippet && npm run copy",
Expand All @@ -12,7 +12,7 @@
"lint": "eslint ./sdk/src ./layout/src ./test ./demo/src --fix",
"test": "TZ=UTC jest --config ./test/jest.config.ts",
"prepublishOnly": "npm-run-all lint test",
"copy": "cp LICENSE README.md sdk"
"copy": "cp LICENSE README.md CHANGELOG.md sdk"
},
"main": "sdk/dist/adjust-smart-banner.js",
"types": "sdk/dist/adjust-smart-banner.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adjustcom/smart-banner-sdk",
"version": "1.0.0",
"version": "1.0.1",
"description": "Adjust Smart Banner SDK",
"scripts": {
"build:sdk": "webpack --config ./webpack.config.js",
Expand Down
24 changes: 20 additions & 4 deletions sdk/src/domain/tracker-builder.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Context, DeeplinkData } from '../data/types';
import { parseGetParams } from '@utils/parse-get-params';
import { interpolate } from '@utils/template-interpolaion';
import { omitNotDefined } from '@utils/object';
import { Context, DeeplinkData } from '../data/types';
import { DeviceOS, getDeviceOS } from '@utils/detect-os';

export interface TrackerData {
template: string;
default_template: string;
context: Context;
}

interface DeeplinkPaths {
deep_link_path: string;
deep_link: string;
}

export function buildSmartBannerUrl(data: TrackerData, pageUrl: string, customDeeplinkData: DeeplinkData) {
const template = data.template;

Expand Down Expand Up @@ -36,16 +42,16 @@ export function buildSmartBannerUrl(data: TrackerData, pageUrl: string, customDe
...deeplink
};

const { result, notReplaced } = interpolate(template, combinedContext);
const { result, notReplaced } = interpolate(adaptTemplate(template, deeplink), combinedContext);

if (notReplaced.length > 0) {
return interpolate(data.default_template, combinedContext).result;
return interpolate(adaptTemplate(data.default_template, deeplink), combinedContext).result;
}

return result;
}

function buildDeeplink(data: Omit<TrackerData, 'default_template'>, customContext: Record<string, string>): Record<string, string> {
function buildDeeplink(data: Omit<TrackerData, 'default_template'>, customContext: Record<string, string>): DeeplinkPaths {
let deeplinkTemplate = data.context.deep_link_path || data.context.deep_link || '';

const context: Record<string, string> = {
Expand All @@ -69,3 +75,13 @@ function buildDeeplink(data: Omit<TrackerData, 'default_template'>, customContex
};
}

function adaptTemplate(template: string, context: DeeplinkPaths): string {
if (getDeviceOS() === DeviceOS.iOS && context.deep_link_path.indexOf('?') > -1) { // if ios deeplink path contains '?'
// then replace '?' in the template with '&' to avoid invalid URL creation
return template.replace('?', '&');
}

// otherwise do nothing with the template
return template;
}

57 changes: 48 additions & 9 deletions test/domain/tracker-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Context } from '@sdk/data/types';
import { buildSmartBannerUrl } from '@sdk/domain/tracker-builder';
import * as DetectOs from '@sdk/utils/detect-os';

jest.mock('@sdk/utils/logger');

describe('Smart Banners tracker link building', () => {
const commonTracker = 'https://{domain}/{tracker}?campaign={campaign}&adgroup={localization_language}';
const iosTracker = 'https://{domain}/{deep_link_path}/adj_t={tracker}?adj_campaign={campaign}&adj_adgroup={localization_language}';
const iosTracker = 'https://{domain}/{deep_link_path}?adj_t={tracker}&adj_campaign={campaign}&adj_adgroup={localization_language}';
const androidTracker = 'https://{domain}/{tracker}?deep_link={deep_link}&campaign={campaign}&adgroup={localization_language}';

const commonContext: Context = {
Expand Down Expand Up @@ -51,7 +52,7 @@ describe('Smart Banners tracker link building', () => {
context: iosContext
};

const expected = 'https://test.domain/some-path/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/some-path?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, emptyCustomData)).toBe(expected);
});
Expand Down Expand Up @@ -81,7 +82,7 @@ describe('Smart Banners tracker link building', () => {
context: iosContext
};

const expected = 'https://test.domain/my-product/t-shirt/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/my-product/t-shirt?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, { iosDeepLinkPath: customDeepLinkPath })).toBe(expected);
});
Expand All @@ -93,7 +94,7 @@ describe('Smart Banners tracker link building', () => {
context: { ...iosContext, ios_deep_link_path: 'my-product/{product}' }
};

const expected = 'https://test.domain/my-product/t-shirt/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/my-product/t-shirt?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, { context: { product: 't-shirt' } })).toBe(expected);
});
Expand All @@ -107,14 +108,35 @@ describe('Smart Banners tracker link building', () => {
context: iosContext
};

const expected = 'https://test.domain/my-product/jeans/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/my-product/jeans?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, {
iosDeepLinkPath: customDeepLinkPath,
context: { product: 'jeans' }
})).toBe(expected);
});

it('builds a valid URL when a search query passed as iosDeepLinkPath', () => {
jest.spyOn(DetectOs, 'getDeviceOS').mockReturnValue(DetectOs.DeviceOS.iOS);

const customDeepLinkPath = 'search?product={product}';

const trackerData = {
template: iosTracker,
default_template: iosTracker,
context: iosContext
};

const expected = 'https://test.domain/search?product=jeans&adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, {
iosDeepLinkPath: customDeepLinkPath,
context: { product: 'jeans' }
})).toBe(expected);

jest.spyOn(DetectOs, 'getDeviceOS').mockRestore();
});

it('builds android tracker with a plain custom deeplink', () => {
const customDeepLinkPath = 'my-product/t-shirt';

Expand Down Expand Up @@ -160,6 +182,23 @@ describe('Smart Banners tracker link building', () => {
context: { product: 'shoes' }
})).toBe(expected);
});

it('builds a valid URL when a search query passed as androidDeepLinkPath', () => {
const customDeepLinkPath = 'search?product={product}';

const trackerData = {
template: androidTracker,
default_template: androidTracker,
context: androidContext
};

const expected = 'https://test.domain/abc123?deep_link=app%3A%2F%2Fsearch%3Fproduct%3Djeans&campaign=banner1&adgroup=en';

expect(buildSmartBannerUrl(trackerData, emptyUrl, {
androidDeepLinkPath: customDeepLinkPath,
context: { product: 'jeans' }
})).toBe(expected);
});
});

describe('Uses GET parameters for interpolation', () => {
Expand All @@ -170,7 +209,7 @@ describe('Smart Banners tracker link building', () => {
context: { ...iosContext, ios_deep_link_path: 'some-path/{page}' }
};

const expected = 'https://test.domain/some-path/hello/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/some-path/hello?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, 'https://some-path/?page=hello', emptyCustomData)).toBe(expected);
});
Expand All @@ -195,7 +234,7 @@ describe('Smart Banners tracker link building', () => {
context: iosContext
};

const expected = 'https://test.domain/some-path/hello/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/some-path/hello?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

expect(buildSmartBannerUrl(trackerData, 'https://some-path/?page=hello', { iosDeepLinkPath: 'some-path/{page}' })).toBe(expected);
});
Expand All @@ -220,7 +259,7 @@ describe('Smart Banners tracker link building', () => {
context: { ...iosContext, ios_deep_link_path: '{path}/{page}' }
};

const expected = 'https://test.domain/long/path/hello/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/long/path/hello?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

const tracker = buildSmartBannerUrl(trackerData, 'https://some-path/?page=hello', { context: { path: 'long/path' } });
expect(tracker).toBe(expected);
Expand All @@ -247,7 +286,7 @@ describe('Smart Banners tracker link building', () => {
context: { ...iosContext, ios_deep_link_path: 'path/{page}' }
};

const expected = 'https://test.domain/path/meow/adj_t=abc123?adj_campaign=banner1&adj_adgroup=en';
const expected = 'https://test.domain/path/meow?adj_t=abc123&adj_campaign=banner1&adj_adgroup=en';

const tracker = buildSmartBannerUrl(trackerData, 'https://some-path/?page=hello', { context: { page: 'meow' } });
expect(tracker).toBe(expected);
Expand Down

0 comments on commit 7840b4a

Please sign in to comment.