Skip to content

Commit 5531870

Browse files
committed
feat: Add transferableUrlParameters option to the embed API
1 parent 87b7824 commit 5531870

File tree

10 files changed

+106
-10
lines changed

10 files changed

+106
-10
lines changed

demo/popup-api.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,17 @@
134134
window.addEventListener('DOMContentLoaded', function () {
135135
document.getElementById('btn-popup').onclick = function(e) {
136136
e.preventDefault()
137-
makeMockPopup({mode: 'popup'}).open()
137+
makeMockPopup({mode: 'popup', transferableUrlParameters: ['utm_source']}).open()
138138
}
139139

140140
document.getElementById('btn-drawer_left').onclick = function(e) {
141141
e.preventDefault()
142-
makeMockPopup({mode: 'drawer_left'}).open()
142+
makeMockPopup({mode: 'drawer_left', transferableUrlParameters: ['utm_source']}).open()
143143
}
144144

145145
document.getElementById('btn-drawer_right').onclick = function(e) {
146146
e.preventDefault()
147-
makeMockPopup({mode: 'drawer_right', width: 300}).open()
147+
makeMockPopup({mode: 'drawer_right', width: 300, transferableUrlParameters: ['utm_source']}).open()
148148
}
149149

150150
let popoverPopup
@@ -164,6 +164,7 @@
164164
mode: 'popover',
165165
width: 400,
166166
height: 400,
167+
transferableUrlParameters: ['utm_source'],
167168
onReady: popoverReadyCallback
168169
})
169170
popoverButton.innerHTML = '...'
@@ -202,6 +203,7 @@
202203
mode: 'side_panel',
203204
width: 400,
204205
height: 400,
206+
transferableUrlParameters: ['utm_source'],
205207
container: sidePanelContainerElement,
206208
onReady: sidePanelReadyCallback
207209
})

demo/popup.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
href="./form/mock.html#foobar=hello"
9696
data-mode="popup"
9797
data-submit-close-delay="4"
98+
data-transferable-url-parameters="utm_source"
9899
target="_blank"
99100
>
100101
Launch me as a popup!
@@ -107,6 +108,7 @@
107108
href="./form/mock.html?foobar=hello"
108109
data-mode="drawer_left"
109110
data-submit-close-delay="4"
111+
data-transferable-url-parameters="utm_source"
110112
target="_blank"
111113
>
112114
Launch me as a drawer!
@@ -119,6 +121,7 @@
119121
data-mode="drawer_right"
120122
data-width="400"
121123
data-submit-close-delay="4"
124+
data-transferable-url-parameters="utm_source"
122125
target="_blank"
123126
>
124127
Launch me as a right drawer!
@@ -134,6 +137,7 @@
134137
data-width="500"
135138
data-height="600"
136139
data-submit-close-delay="4"
140+
data-transferable-url-parameters="utm_source"
137141
target="_blank"
138142
>
139143
<span class="icon">
@@ -155,6 +159,7 @@
155159
data-width="360"
156160
data-height="560"
157161
data-submit-close-delay="4"
162+
data-transferable-url-parameters="utm_source"
158163
target="_blank"
159164
>
160165
<span class="icon">

demo/widget-legacy.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<div
1111
class="typeform-widget"
1212
data-url="./form/mock.html?foobar=hello"
13+
data-transferable-url-parameters="utm_source"
1314
style="width:100%; height:500px;"
1415
></div>
1516

demo/widget.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<div
1111
class="typeform-widget"
1212
data-url="./form/mock.html#foobar=hello"
13+
data-transferable-url-parameters="utm_source"
1314
style="width:100%; height:500px;"
1415
></div>
1516

e2e/spec/functional/popup.spec.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ const popupModes = {
1717
}
1818

1919
const pages = {
20-
'/popup.html': 'embed code',
21-
'/popup-api.html': 'API'
20+
'/popup.html?utm_source=facebook ': 'embed code',
21+
'/popup-api.html?utm_source=facebook': 'API'
2222
}
2323

2424
Object.keys(popupModes).forEach(popupMode => {
@@ -35,6 +35,10 @@ Object.keys(popupModes).forEach(popupMode => {
3535
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
3636
})
3737

38+
it('Passes Browser URL parameters', () => {
39+
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /utm_source=facebook/)
40+
})
41+
3842
it('Closes Embed Popup clicking on the close button', () => {
3943
if (popupMode === 'popover' || popupMode === 'side_panel') {
4044
closePopupViaButton(`#btn-${popupMode}`) // no close button, popup closes via the button that opened it

e2e/spec/functional/widget.spec.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('Embed Widget in div with position:absolute on mobile', () => {
1010
describe('Basic Embed Widget', () => {
1111
describe('On Desktop', () => {
1212
before(() => {
13-
open('/widget.html')
13+
open('/widget.html?utm_source=facebook')
1414
})
1515

1616
it('Loads correctly the basic embed widget', () => {
@@ -20,11 +20,15 @@ describe('Basic Embed Widget', () => {
2020
it('Passes hidden field parameter', () => {
2121
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
2222
})
23+
24+
it('Passes Browser URL parameters', () => {
25+
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /utm_source=facebook/)
26+
})
2327
})
2428

2529
describe('On Mobile', () => {
2630
before(() => {
27-
openOnMobile('/widget.html')
31+
openOnMobile('/widget.html?utm_source=facebook')
2832
})
2933

3034
it('Loads correctly the basic embed widget', () => {
@@ -34,13 +38,17 @@ describe('Basic Embed Widget', () => {
3438
it('Passes hidden field parameter', () => {
3539
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
3640
})
41+
42+
it('Passes Browser URL parameters', () => {
43+
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /utm_source=facebook/)
44+
})
3745
})
3846
})
3947

4048
describe('Basic Embed Widget with Legacy Hidden Fields', () => {
4149
describe('On Desktop', () => {
4250
before(() => {
43-
open('/widget-legacy.html')
51+
open('/widget-legacy.html?utm_source=facebook')
4452
})
4553

4654
it('Loads correctly the basic embed widget', () => {
@@ -50,11 +58,15 @@ describe('Basic Embed Widget with Legacy Hidden Fields', () => {
5058
it('Passes hidden field parameter', () => {
5159
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
5260
})
61+
62+
it('Passes Browser URL parameters', () => {
63+
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /utm_source=facebook/)
64+
})
5365
})
5466

5567
describe('On Mobile', () => {
5668
before(() => {
57-
openOnMobile('/widget-legacy.html')
69+
openOnMobile('/widget-legacy.html?utm_source=facebook')
5870
})
5971

6072
it('Loads correctly the basic embed widget', () => {
@@ -64,6 +76,10 @@ describe('Basic Embed Widget with Legacy Hidden Fields', () => {
6476
it('Passes hidden field parameter', () => {
6577
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /foobar=hello/)
6678
})
79+
80+
it('Passes Browser URL parameters', () => {
81+
cy.get(IFRAME_SELECTOR).should('have.attr', 'src').and('match', /utm_source=facebook/)
82+
})
6783
})
6884
})
6985

src/core/make-popup.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import {
77
ensureMetaViewport,
88
noop
99
} from './utils'
10+
import {
11+
transferUrlParametersToQueryStrings
12+
} from './utils/url-parameters-transfer'
1013
import randomString from './utils/random-string'
1114
import {
1215
isMobile,
@@ -45,6 +48,7 @@ const buildOptions = (embedId, options) => {
4548
hideHeaders: false,
4649
hideScrollbars: false,
4750
disableTracking: false,
51+
transferableUrlParameters: options.transferableUrlParameters || [],
4852
onSubmit: noop,
4953
open: null,
5054
openValue: null,
@@ -72,9 +76,12 @@ const renderComponent = (params, options) => {
7276
onSubmit
7377
} = options
7478

79+
let queryStrings = replaceExistingKeys(options, queryStringKeys)
80+
queryStrings = transferUrlParametersToQueryStrings(options.transferableUrlParameters, queryStrings)
81+
7582
const urlWithQueryString = appendParamsToUrl(
7683
url,
77-
replaceExistingKeys(options, queryStringKeys)
84+
queryStrings
7885
)
7986

8087
if (!isMobile(navigator.userAgent) && isScreenBig()) {

src/core/make-widget.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import {
77
noop,
88
omit
99
} from './utils'
10+
import {
11+
transferUrlParametersToQueryStrings
12+
} from './utils/url-parameters-transfer'
1013
import {
1114
isMobile
1215
} from './utils/mobile-detection'
@@ -19,6 +22,7 @@ const defaultOptions = {
1922
hideHeaders: false,
2023
hideScrollbars: false,
2124
disableTracking: false,
25+
transferableUrlParameters: [],
2226
onSubmit: noop
2327
}
2428

@@ -38,6 +42,7 @@ export default function makeWidget (element, url, options) {
3842
const enabledFullscreen = isMobile(navigator.userAgent)
3943

4044
let queryStrings = replaceExistingKeys(options, queryStringKeys)
45+
queryStrings = transferUrlParametersToQueryStrings(options.transferableUrlParameters, queryStrings)
4146

4247
if (enabledFullscreen) {
4348
queryStrings = {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const urlSearchToParams = (search) => {
2+
var params = {}
3+
if (search !== '' && search !== null) {
4+
var vars = search.split('&')
5+
for (var i = 0; i < vars.length; i++) {
6+
var pair = vars[i].split('=')
7+
params[pair[0]] = decodeURIComponent(pair[1])
8+
}
9+
}
10+
return params
11+
}
12+
13+
export const transferUrlParametersToQueryStrings = (transferableUrlParameters, queryStrings) => {
14+
const urlSearchString = window.location.search.substr(1)
15+
const urlSearchParams = urlSearchToParams(urlSearchString)
16+
const queryStringsWithTransferedParams = { ...queryStrings }
17+
transferableUrlParameters.forEach(transferableParam => {
18+
if (!(transferableParam in queryStrings)) {
19+
queryStringsWithTransferedParams[transferableParam] = urlSearchParams[transferableParam]
20+
}
21+
})
22+
return queryStringsWithTransferedParams
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { transferUrlParametersToQueryStrings } from './url-parameters-transfer'
2+
3+
describe('transferUrlParametersToQueryStrings', () => {
4+
const { location } = window
5+
6+
beforeAll(() => {
7+
delete window.location
8+
window.location = { search: '?foo=jason&bar=rachel&utm_medium=cpc&utm_campaign=camp2008&utm_source=instagram&embed-hide-footer=false' }
9+
})
10+
11+
afterAll(() => {
12+
window.location = location
13+
})
14+
15+
it('should return ?foo=jason&bar=rachel&utm_medium=cpc&utm_campaign=camp2008&utm_source=instagram&embed-hide-footer=false', () => {
16+
expect(window.location.search).toEqual('?foo=jason&bar=rachel&utm_medium=cpc&utm_campaign=camp2008&utm_source=instagram&embed-hide-footer=false')
17+
})
18+
19+
it('transfer the parameters of the URL in the query strings', () => {
20+
const urlParameters = ['foo', 'bar']
21+
const queryStrings = {}
22+
const queryStringWithTransferedUrlParameters = transferUrlParametersToQueryStrings(urlParameters, queryStrings)
23+
expect(queryStringWithTransferedUrlParameters).toEqual({ foo: 'jason', bar: 'rachel' })
24+
})
25+
26+
it('does not override existing queryString for embed configuration', () => {
27+
const urlParameters = ['foo', 'bar', 'embed-hide-footer']
28+
const queryStrings = { 'embed-hide-footer': true }
29+
const queryStringWithTransferedUrlParameters = transferUrlParametersToQueryStrings(urlParameters, queryStrings)
30+
expect(queryStringWithTransferedUrlParameters).toEqual({ foo: 'jason', bar: 'rachel', 'embed-hide-footer': true })
31+
})
32+
})

0 commit comments

Comments
 (0)