Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DO NOT MERGE!!! #1

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/browser/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ clean: ## Clean the build directory
rm -rf dist generated
.PHONY: clean

attribution: ## Replaces cookie names in the standalone build and remove last line
@gsed -i 's/\"ajs_group_id\"/\"_attrg\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"ajs_group_properties\"/\"attr_group_properties\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"ajs_user_id\"/\"_attru\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"ajs_user\"/\"none\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"ajs_user_traits\"/\"attr_user_traits\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"ajs_anonymous_id\"/\"_attrb\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"_sio\"/\"_attrb\"/g' ./dist/umd/standalone.js
@gsed -i 's/\"analytics.js\"/\"attribution.js\"/g' ./dist/umd/standalone.js
@gsed -i 's/\/\/# sourceMappingURL=standalone.js.map//g' ./dist/umd/standalone.js
.PHONY: attribution

## Test Commands

tdd: node_modules ## Runs unit tests in watch mode
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"jest": "yarn run -T jest",
"concurrently": "yarn run -T concurrently",
"watch": "yarn concurrently 'NODE_ENV=production WATCH=true yarn umd --watch' 'yarn pkg --watch'",
"build": "yarn clean && yarn build-prep && yarn concurrently 'NODE_ENV=production yarn umd' 'yarn pkg' 'yarn cjs'",
"build": "yarn clean && yarn build-prep && NODE_ENV=production yarn umd && yarn pkg && yarn cjs && make attribution",
"release:cdn": "yarn . build && NODE_ENV=production bash scripts/release.sh && NODE_ENV=stage bash scripts/release.sh",
"pkg": "yarn tsc -p tsconfig.build.json",
"cjs": "yarn tsc -p tsconfig.build.json --outDir ./dist/cjs --module commonjs",
Expand Down
17 changes: 8 additions & 9 deletions packages/browser/src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
RemotePlugin,
} from '../plugins/remote-loader'
import type { RoutingRule } from '../plugins/routing-middleware'
import { segmentio, SegmentioSettings } from '../plugins/segmentio'
import { segmentio } from '../plugins/segmentio'
import { validation } from '../plugins/validation'
import {
AnalyticsBuffered,
Expand All @@ -31,6 +31,7 @@ import { ClassicIntegrationSource } from '../plugins/ajs-destination/types'
import { attachInspector } from '../core/inspector'
import { Stats } from '../core/stats'
import { setGlobalAnalyticsKey } from '../lib/global-analytics-helper'
import { addAtbIntegrations } from '../plugins/attribution/attribution-integrations'

export interface LegacyIntegrationConfiguration {
/* @deprecated - This does not indicate browser types anymore */
Expand Down Expand Up @@ -266,11 +267,7 @@ async function registerPlugins(

if (!shouldIgnoreSegmentio) {
toRegister.push(
await segmentio(
analytics,
mergedSettings['Segment.io'] as SegmentioSettings,
legacySettings.integrations
)
await segmentio(analytics, options, legacySettings.integrations)
)
}

Expand Down Expand Up @@ -309,9 +306,7 @@ async function loadAnalytics(
// this is an ugly side-effect, but it's for the benefits of the plugins that get their cdn via getCDN()
if (settings.cdnURL) setGlobalCDNUrl(settings.cdnURL)

let legacySettings =
settings.cdnSettings ??
(await loadLegacySettings(settings.writeKey, settings.cdnURL))
let legacySettings: any = { integrations: {} }

if (options.updateCDNSettings) {
legacySettings = options.updateCDNSettings(legacySettings)
Expand Down Expand Up @@ -343,6 +338,10 @@ async function loadAnalytics(
classicIntegrations
)

if (options.atbIntegrations) {
addAtbIntegrations(options.atbIntegrations)
}

const search = window.location.search ?? ''
const hash = window.location.hash ?? ''

Expand Down
10 changes: 2 additions & 8 deletions packages/browser/src/browser/standalone-analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,8 @@ function getWriteKey(): string | undefined {
}

export async function install(): Promise<void> {
const writeKey = getWriteKey()
const options = getGlobalAnalytics()?._loadOptions ?? {}
if (!writeKey) {
console.error(
'Failed to load Write Key. Make sure to use the latest version of the Segment snippet, which can be found in your source settings.'
)
return
}
const options: any = getGlobalAnalytics()?._loadOptions ?? {}
const writeKey = getWriteKey() || options.projectId

setGlobalAnalytics(
(await AnalyticsBrowser.standalone(writeKey, options)) as AnalyticsSnippet
Expand Down
58 changes: 58 additions & 0 deletions packages/browser/src/core/analytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export interface InitOptions {
plan?: Plan
retryQueue?: boolean
obfuscate?: boolean
atbIntegrations?: Integrations
/**
* This callback allows you to update/mutate CDN Settings.
* This is called directly after settings are fetched from the CDN.
Expand Down Expand Up @@ -251,6 +252,63 @@ export class Analytics
return this._universalStorage
}

loadScript(
src: string,
attributes?: Record<string, string>
): Promise<HTMLScriptElement> {
function findScript(src: string): HTMLScriptElement | undefined {
const scripts = Array.prototype.slice.call(
window.document.querySelectorAll('script')
)
return scripts.find((s) => s.src === src)
}

const found = findScript(src)

if (found !== undefined) {
const status = found?.getAttribute('status')

if (status === 'loaded') {
return Promise.resolve(found)
}

if (status === 'loading') {
return new Promise((resolve, reject) => {
found.addEventListener('load', () => resolve(found))
found.addEventListener('error', (err) => reject(err))
})
}
}

return new Promise((resolve, reject) => {
const script = window.document.createElement('script')

script.type = 'text/javascript'
script.src = src
script.async = true

script.setAttribute('status', 'loading')
for (const [k, v] of Object.entries(attributes ?? {})) {
script.setAttribute(k, v)
}

script.onload = (): void => {
script.onerror = script.onload = null
script.setAttribute('status', 'loaded')
resolve(script)
}

script.onerror = (): void => {
script.onerror = script.onload = null
script.setAttribute('status', 'error')
reject(new Error(`Failed to load ${src}`))
}

const tag = window.document.getElementsByTagName('script')[0]
tag.parentElement?.insertBefore(script, tag)
})
}

async track(...args: EventParams): Promise<DispatchedEvent> {
const [name, data, opts, cb] = resolveArguments(...args)

Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/core/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const SEGMENT_API_HOST = 'api.segment.io/v1'
export const SEGMENT_API_HOST = 'track.attributionapp.com/v1'
2 changes: 1 addition & 1 deletion packages/browser/src/lib/global-analytics-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AnalyticsSnippet } from '../browser/standalone-interface'
/**
* Stores the global window analytics key
*/
let _globalAnalyticsKey = 'analytics'
let _globalAnalyticsKey = 'Attribution'

/**
* Gets the global analytics/buffer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { loadScript } from '../../lib/load-script'

async function loadIntegration(name: string, params: any) {
if (params) console.log(params, name)

const path = 'https://scripts.attributionapp.com/v3'
const fullPath = `${path}/${name}.js`

try {
await loadScript(fullPath)
} catch (err) {
console.log(err)
}
}

export function addAtbIntegrations(integrations: any) {
Object.keys(integrations).forEach(async (key) => {
const params = integrations[key]
await loadIntegration(key, params)
})
}
2 changes: 1 addition & 1 deletion packages/browser/src/plugins/segmentio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function onAlias(analytics: Analytics, json: JSON): JSON {

export async function segmentio(
analytics: Analytics,
settings?: SegmentioSettings,
settings?: any,
integrations?: LegacySettings['integrations']
): Promise<Plugin> {
// Attach `pagehide` before buffer is created so that inflight events are added
Expand Down
6 changes: 3 additions & 3 deletions packages/browser/src/plugins/segmentio/normalize.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Analytics } from '../../core/analytics'
import { LegacySettings } from '../../browser'
import { SegmentFacade } from '../../lib/to-facade'
import { SegmentioSettings } from './index'

export function normalize(
analytics: Analytics,
json: ReturnType<SegmentFacade['json']>,
settings?: SegmentioSettings,
settings?: any,
integrations?: LegacySettings['integrations']
): object {
const user = analytics.user()

delete json.options

json.writeKey = settings?.apiKey
json.projectId = settings?.projectId

json.userId = json.userId || user.id()
json.anonymousId = json.anonymousId || user.anonymousId()
Expand Down Expand Up @@ -53,7 +53,7 @@ export function normalize(
const bundledConfigIds: string[] = []

bundled.sort().forEach((name) => {
;(configIds[name] ?? []).forEach((id) => {
;(configIds[name] ?? []).forEach((id: any) => {
bundledConfigIds.push(id)
})
})
Expand Down
Loading