detail page port
This commit is contained in:
107
composables/useKlaviyo.js
Normal file
107
composables/useKlaviyo.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
// Wraps Klaviyo's legacy client-side list-subscribe endpoint.
|
||||
// Klaviyo requires any non-standard property names to be declared in `$fields`
|
||||
// for them to be persisted on the profile — this composable handles that for you.
|
||||
|
||||
const ENDPOINT = 'https://manage.kmail-lists.com/ajax/subscriptions/subscribe'
|
||||
|
||||
export default () => {
|
||||
const loading = ref(false)
|
||||
const success = ref(false)
|
||||
const error = ref('')
|
||||
|
||||
const reset = () => {
|
||||
loading.value = false
|
||||
success.value = false
|
||||
error.value = ''
|
||||
}
|
||||
|
||||
const subscribe = async ({
|
||||
listId,
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
name,
|
||||
source,
|
||||
properties = {},
|
||||
} = {}) => {
|
||||
if (!listId) {
|
||||
error.value = 'Missing listId'
|
||||
return
|
||||
}
|
||||
if (!email) {
|
||||
error.value = 'Missing email'
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
// `name` is a convenience: first token → first_name, rest → last_name
|
||||
let fName = firstName
|
||||
let lName = lastName
|
||||
if (name && !fName && !lName) {
|
||||
const parts = name.trim().split(/\s+/)
|
||||
fName = parts.shift()
|
||||
lName = parts.join(' ') || undefined
|
||||
}
|
||||
|
||||
const body = { g: listId, email }
|
||||
if (fName) body.first_name = fName
|
||||
if (lName) body.last_name = lName
|
||||
|
||||
const extraFields = []
|
||||
if (source) {
|
||||
body.$source = source
|
||||
extraFields.push('$source')
|
||||
}
|
||||
for (const [key, value] of Object.entries(properties)) {
|
||||
if (value === undefined || value === null || value === '') continue
|
||||
body[key] = value
|
||||
extraFields.push(key)
|
||||
}
|
||||
if (extraFields.length) body.$fields = extraFields.join(',')
|
||||
|
||||
try {
|
||||
await $fetch(ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cache-Control': 'no-cache',
|
||||
},
|
||||
body: new URLSearchParams(body),
|
||||
})
|
||||
success.value = true
|
||||
} catch (err) {
|
||||
console.error('useKlaviyo subscribe error', err)
|
||||
error.value =
|
||||
err?.toString().split('Error: ')[1] || 'Subscription failed'
|
||||
}
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// Fires a Klaviyo event (metric) — append-only history, good for things
|
||||
// segments will slice on like "Submitted RSVP" with per-event properties.
|
||||
// Throws on failure; doesn't touch the shared loading/success/error refs,
|
||||
// so callers can pair it with subscribe() without state collisions.
|
||||
const track = ({ email, metric, properties = {} }) => {
|
||||
if (!email || !metric) {
|
||||
throw new Error('useKlaviyo.track: email and metric are required')
|
||||
}
|
||||
return $fetch('/api/klaviyo-track', {
|
||||
method: 'POST',
|
||||
body: { email, metric, properties },
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
success,
|
||||
error,
|
||||
subscribe,
|
||||
track,
|
||||
reset,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user