-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheader-custom-code.html
More file actions
394 lines (361 loc) · 16.9 KB
/
header-custom-code.html
File metadata and controls
394 lines (361 loc) · 16.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
<!-- Segment initialization (but don't track page yet) -->
<script>
!function () {
var analytics = window.analytics = window.analytics || []; if (!analytics.initialize) if (analytics.invoked) window.console && console.error && console.error("Segment snippet included twice."); else {
analytics.invoked = !0; analytics.methods = ["trackSubmit", "trackClick", "trackLink", "trackForm", "pageview", "identify", "reset", "group", "track", "ready", "alias", "debug", "page", "once", "off", "on", "addSourceMiddleware", "addIntegrationMiddleware", "setAnonymousId", "addDestinationMiddleware"]; analytics.factory = function (e) { return function () { var t = Array.prototype.slice.call(arguments); t.unshift(e); analytics.push(t); return analytics } }; for (var e = 0; e < analytics.methods.length; e++) { var key = analytics.methods[e]; analytics[key] = analytics.factory(key) } analytics.load = function (key, e) { var t = document.createElement("script"); t.type = "text/javascript"; t.async = !0; t.src = "https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js"; var n = document.getElementsByTagName("script")[0]; n.parentNode.insertBefore(t, n); analytics._loadOptions = e }; analytics._writeKey = "voF0TJjZHNsenbBzw8VeDIYggupAmfuj";; analytics.SNIPPET_VERSION = "4.15.3";
analytics.load("voF0TJjZHNsenbBzw8VeDIYggupAmfuj");
}
}();
</script>
<!-- A/B tests -->
<script>
let params = new URL(window.location).searchParams;
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
let isRunningExperiment = false;
function setExperimentCookie(experimentId, variant, days) {
const expires = new Date(Date.now() + days * 864e5).toUTCString();
document.cookie = experimentId + '=' + encodeURIComponent(variant) + '; expires=' + expires + '; path=/';
}
function getExperimentCookie(experimentId) {
return document.cookie.split('; ').find(row => row.startsWith(experimentId + '='))?.split('=')[1];
}
const EXPERIMENTS = {
HERO: 'hero-2025feb',
FLATTERED: 'flat-v'
};
const heroLive = false;
const flatteredLive = false;
// Mobile hero A/B test
if (heroLive && isMobile && window.location.pathname === '/') {
isRunningExperiment = true;
let heroVariant = params.get(EXPERIMENTS.HERO)?.toLowerCase();
// If no URL param, check cookie or assign random
if (!heroVariant) {
heroVariant = getExperimentCookie(EXPERIMENTS.HERO) ||
['control', 'a', 'b'][Math.floor(Math.random() * 3)];
// Update URL since variant came from cookie or random
const newUrl = new URL(window.location);
newUrl.searchParams.set(EXPERIMENTS.HERO, heroVariant);
history.replaceState({}, '', newUrl);
params = new URL(window.location).searchParams;
}
// Always ensure cookie is set/refreshed
setExperimentCookie(EXPERIMENTS.HERO, heroVariant, 7);
// Show variant
document.addEventListener("DOMContentLoaded", function () {
function showTestImage() {
document.querySelectorAll('.hero-image-a').forEach(el => { el.style.display = 'block'; });
document.querySelectorAll('.login-btn').forEach(el => {
el.style.border = '1px solid rgba(128, 128, 128, 0.3)';
});
document.querySelectorAll('.black-logo').forEach(el => { el.style.display = 'block'; });
document.getElementById('header').style.marginBottom = '0px';
//Hide control hero
document.querySelectorAll('.hero-image').forEach(el => el.remove());
document.querySelectorAll('.white-logo').forEach(el => { el.style.display = 'none'; });
}
const currentVariant = params.get(EXPERIMENTS.HERO)?.toLowerCase();
if (currentVariant === 'a') {
heroTitle.innerHTML = 'Din smarta säljtjänst för second hand';
heroText.innerHTML = 'Mai är din AI-assistent som säljer kläder åt dig på Tradera, Vestiaire och andra marknadsplatser. Mai sköter allt – du behåller 80%. Prova första gratis.';
showTestImage()
} else if (currentVariant === 'b') {
heroTitle.innerHTML = 'Sälj utan krångel, Mai säljer kläderna åt dig';
heroText.innerHTML = 'Mai hjälper dig sälja på utvalda marknadsplatser på några få klick. Mai sköter allt, från köparkontakt till frakt, så du slipper. Du behåller 80%. Prova första gratis.';
showTestImage()
}
// Track which hero variant was shown
analytics.track("Experiment Viewed", {
experimentID: EXPERIMENTS.HERO,
variantID: heroVariant
});
});
}
// Flattered page A/B test
if (flatteredLive && isMobile && window.location.pathname === '/flattered') {
let flatteredVariant = params.get(EXPERIMENTS.FLATTERED)?.toLowerCase() || '';
if (!flatteredVariant) {
flatteredVariant = getExperimentCookie(EXPERIMENTS.FLATTERED) ||
['a', 'b'][Math.floor(Math.random() * 2)];
// Update URL since variant came from cookie or random
const newUrl = new URL(window.location);
newUrl.searchParams.set(EXPERIMENTS.FLATTERED, flatteredVariant);
history.replaceState({}, '', newUrl);
params = new URL(window.location).searchParams;
}
// Always ensure cookie is set/refreshed
setExperimentCookie(EXPERIMENTS.FLATTERED, flatteredVariant);
// Show variant
document.addEventListener("DOMContentLoaded", function () {
const currentVariant = params.get(EXPERIMENTS.FLATTERED)?.toLowerCase();
if (currentVariant === 'a') {
console.log('A: Update hero');
heroTitle.innerHTML = 'Låt dina plagg från Flattered leva vidare';
heroText.innerHTML = 'Flattered är rotad i skandinavisk kvalitet och hantverk, varje produkt är skapad för att hålla över tid. Sälj vidare det som du inte längre använder och få 100% av vinsten i presentkort på flattered.com eller 80% via Swish.';
sellButtonText.innerHTML = 'Sälj med Mai';
sellBtnMaiLogo.style.display = 'block';
sellBtnPlusIcon.style.display = 'none';
platformsSection.style.display = 'none';
} else if (currentVariant === 'b') {
console.log('B: Do nothing');
}
});
}
// App webview
if (!params.has('app')) {
if (localStorage.getItem('authUserId')) {
if (window.location.pathname === '/' || window.location.pathname === '/sign-in') {
location.href = '/private' + window.location.search;
}
} else {
const protectedPages = ['/private', '/personal-id-form', '/address-form', '/item', '/edit-item',
'/order-bags', '/settings', '/user-contact', '/referral', '/trusted-seller-status'];
const hasSParam = params.has('s') && params.get('s').length >= 3;
const path = window.location.pathname;
if (protectedPages.includes(path) || (hasSParam && path === '/')) {
location.href = './sign-in' + window.location.search;
}
}
}
let errorHandler;
const user = {
value: null,
callbacks: [],
get current() {
return this.value;
},
set current(newVal) {
try {
const oldEmail = this.value?.email;
const oldPhone = this.value?.phoneNumber;
this.value = newVal;
if (newVal) {
console.log(`user set current calling ${this.callbacks?.length} callbacks`);
this.callbacks.forEach((cb) => {
typeof cb === 'function' && cb(newVal)
});
this.callbacks = [];
}
} catch (e) {
console.log('Error in set current user:', JSON.stringify(e));
}
},
async whenSet(cb) {
if (this.value) {
cb(this.value);
} else {
this.callbacks.push(cb);
}
},
};
const authUser = {
value: null,
callbacks: [],
get current() {
return this.value;
},
set current(newVal) {
if (this.value && newVal && newVal.uid === this.value.uid) {
console.log('Not setting authUser, it is already set');
return;
}
if (!newVal) {
this.value = null;
return;
}
this.value = {
uid: newVal.uid, email: newVal.email, phoneNumber: newVal.phoneNumber,
providerData: [{ providerId: newVal?.providerData?.[0]?.providerId }], metadata: { creationTime: newVal.metadata?.creationTime },
emailVerified: newVal.emailVerified, personalId: newVal.personalId
};
if (newVal.uid && errorHandler) {
errorHandler.setUser(newVal.uid);
}
if (newVal) {
this.callbacks.forEach((cb) => {
typeof cb === 'function' && cb(newVal)
});
this.callbacks = [];
}
},
whenSet(cb) {
if (this.value) {
cb(this.value);
} else {
this.callbacks.push(cb);
}
},
};
const brandPartners = {
'Flattered': {
url: 'flattered.com',
name: 'Flattered',
maiShopPath: '/flattered',
featureEnabled: true,
giftCards: false
},
'Filippa K': {
url: 'filippa-k.com',
name: 'Filippa K',
maiShopPath: '/filippa-k',
featureEnabled: true,
giftCards: true
},
'Blankens': {
url: 'blankens.com',
name: 'Blankens',
maiShopPath: '/blankens',
featureEnabled: true,
giftCards: true
},
'Eytys': {
url: 'eytys.com',
name: 'EYTYS',
maiShopPath: '/eytys',
featureEnabled: true,
giftCards: false
}
};
const isBrandPartner = (brandName) => {
return Object.values(brandPartners)
.some(partner =>
partner.name.toUpperCase() === brandName?.toUpperCase() &&
partner.featureEnabled === true
);
};
const isGiftCardPartner = (brandName) => {
return Object.values(brandPartners).find(partner =>
partner.name.toUpperCase() === brandName?.toUpperCase() &&
partner.featureEnabled === true &&
partner.giftCards === true
);
};
if (!authUser.current && localStorage.getItem('authUser') && localStorage.getItem('idToken')) {
const p = new URL(window.location).searchParams
const savedUser = localStorage.getItem('sessionUser') ? JSON.parse(localStorage.getItem('sessionUser')) : undefined;
if (!p.has('s') || (savedUser && savedUser.signInInfoKey === p.get('s'))) {
console.log('Restoring logged in user from localStorage');
// Restore user if no s param or signInInfoKey matches s param
authUser.current = JSON.parse(localStorage.getItem('authUser'));
if (!user.current && localStorage.getItem('sessionUser')) {
user.current = JSON.parse(localStorage.getItem('sessionUser'));
}
}
}
const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
</script>
<!-- Track page -->
<script>
analytics.ready(function() {
if (isRunningExperiment) {
// Wait for URL updates if running experiment
setTimeout(() => {
analytics.page();
console.log('Page tracked with experiment URL:', window.location.href);
}, 50);
} else {
// Track immediately if no experiments
analytics.page();
console.log('Page tracked immediately:', window.location.href);
}
});
</script>
<!-- CodeCrumbs -->
<script>
!function (e, t) { e[t] = new Proxy(e[t] || {}, { get: (e, o) => new Proxy(e[o] || function () { }, { apply: (n, r, a) => { const c = () => e[o](...a); "complete" === document.readyState ? c() : document.addEventListener("readystatechange", (n => { "complete" === n.target.readyState && (e?.[o] ? c() : console.error(`${t}.${o} is not a function. Did it load correctly from the CDN? If not, did you use the correct name.`)) })) } }) }) }(globalThis, "CodeCrumbs");
</script>
<!-- Google Tag Manager -->
<script>(function (w, d, s, l, i) {
w[l] = w[l] || []; w[l].push({
'gtm.start':
new Date().getTime(), event: 'gtm.js'
}); var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-KWV4J65');</script>
<!-- End Google Tag Manager -->
<meta name="facebook-domain-verification" content="5l4794w9fadbt3l14enhwey0lzhzde" />
<meta name="facebook-domain-verification" content="9kx1fbpoujkbxq9m2hnaqyabbntrur" />
<meta name="facebook-domain-verification" content="ore0osqnkep3dhvgk26w1slabjrvud" />
<style>
*:focus {
outline: 0 !important;
}
html {
-webkit-tap-highlight-color: rgba(255, 255, 255, 0.4);
}
a>div {
-webkit-tap-highlight-color: transparent !important;
}
</style>
<!-- script for FAQPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{
"@type": "Question",
"name": "Vad skiljer Mai från andra tjänster?",
"acceptedAnswer": {
"@type": "Answer",
"text": "- Vi lägger upp på flera plattformar för att nå fler köpare. Det resulterar i att vi får en högre andel sålt, och ofta till ett högre pris.\n\n- Du har plagget hemma medan vi säljer det åt dig, och det skickas när plagget är sålt med våra påsar. Ombudet skriver ut fraktsedel åt dig med vår QR-kod.\n\n- Vi hjälper dig att sälja second hand online. Vi säljer i vårt namn och har kontakt med alla köpare och prutare. Du kan vara helt anonym."
}
},{
"@type": "Question",
"name": "Kostar det någonting att lägga upp ett plagg på Mai?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Nej, det är helt gratis. Vi tar endast betalt när det blir sålt, och då tar vi 20% i kommission, men minst 50kr och max 500kr."
}
},{
"@type": "Question",
"name": "Hur lång tid tar det att få saker sålt?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Många plagg säljer vi redan efter en vecka från det att de laddas upp hos oss. Inom 30 dagar har vi sålt 70%. Får vi det inte sålt inom 30 dagar så meddelar vi dig det, och eftersom du har plagget hemma kan du bestämma vad du vill göra med det."
}
},{
"@type": "Question",
"name": "Hur många plagg kan jag lägga upp samtidigt?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Du kan lägga upp hur många plagg som helst samtidigt. Vi gör en bedömning av andrahandsvärdet på plagget och säljer det som vi bedömer har ett andrahandsvärde över 150kr."
}
},{
"@type": "Question",
"name": "Är det något ni inte tar emot?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Vi tar inte emot saker med för lågt andrahandsvärde, det rekommenderar vi att du donerar istället. Exempel på saker vi ofta tackar nej till är basplagg från fast-fashion varumärken, kläder i dåligt skick, och saker där nypriset var under 300kr. Vi är bäst på att sälja begagnade märkeskläder från skandinaviska varumärken."
}
},{
"@type": "Question",
"name": "Hur får jag betalt?",
"acceptedAnswer": {
"@type": "Answer",
"text": "När du skickat iväg det sålda plagget får du betalt samma dag via Swish. Vi gör det smidigt för dig att skicka plagget genom att förse dig med både påse samt en QR-kod som du visar ombudet som skriver ut fraktsedeln åt dig."
}
},{
"@type": "Question",
"name": "Vad händer om jag redan sålt plagget själv?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Om du vill avbryta försäljningen hos oss innan vi hunnit sälja det så kan vi komma att ta ut en avgift på 50kr för att ersätta det arbete vi redan lagt ned på plagget.\n\nOm vi hunnit sälja plagget men du ändå sålt det på annat håll och därför inte kan skicka det till vår köpare, så tar vi ut en avgift på 100kr. Detta är för att täcka kostnader vi redan haft för att skicka påsen samt andra kostnader som det innebär för oss att avbryta köpet."
}
},{
"@type": "Question",
"name": "Kan jag sälja mitt plagg med andra tjänster samtidigt?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Nej, det är inte kompatibelt att sälja ditt plagg med andra tjänster samtidigt som du säljer med oss. Försäljning med oss är bindande och du behöver kunna skicka plagget när något säljs. Läs om konsekvenserna i frågan ovan: \"Vad händer om jag redan sålt plagget själv?\""
}
},{
"@type": "Question",
"name": "Hur beräknas 80% av vinsten som jag får vid en försäljning?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Vårt mål är att nå ut till så många köpare som möjligt, det gör vi genom att publicera på flertalet plattformar. Annonsavgiften skiljer sig åt på olika plattformar, så vi säljer varan på den plattform som får högst vinst efter avgiften. De 80% som du får utbetalt räknas alltså på vinsten efter att annonsavgiften är avdragen. Genom Mai har du en bättre, förhandlad annonsavgift, än vad du skulle få om du annonserade själv som privatperson."
}
}]
}
</script>