Vue ile Pushizo Web SDK
@pushizo/web Vue 3'te bir plugin ile başlatılır; bileşenler usePushizo() composable'ı üzerinden SDK'ya, hazır olma durumuna ve abonelik durumuna (reaktif) erişir. Nuxt 3 için yalnızca istemci tarafında çalışan bir…
@pushizo/web Vue 3'te bir plugin ile başlatılır; bileşenler usePushizo() composable'ı üzerinden SDK'ya, hazır olma durumuna ve abonelik durumuna (reaktif) erişir. Nuxt 3 için yalnızca istemci tarafında çalışan bir plugin dosyası yeterlidir.
1. Kurulum
npm install @pushizo/web
```text
Service worker site kökünde: Vite projelerinde `public/PushizoSDKWorker.js`, Nuxt'ta `public/PushizoSDKWorker.js`.
```js
// public/PushizoSDKWorker.js
const apiUrl = new URL(self.location.href).searchParams.get('apiUrl') || 'https://api.example.com';
importScripts(`${apiUrl.replace(/\/$/, '')}/sdk-web/PushizoSDKWorker.js`);
```text
Ortam: `VITE_HS_APP_ID`, `VITE_HS_API_URL` (Nuxt: `NUXT_PUBLIC_HS_APP_ID`, `NUXT_PUBLIC_HS_API_URL` → `runtimeConfig.public`).
## 2. Plugin ve composable
```ts
// src/pushizo.ts
import { inject, ref, type App, type InjectionKey, type Ref } from 'vue';
import Pushizo, { type PushizoSdk, type InitOptions, type PushSubscriptionState } from '@pushizo/web';
export interface PushizoState {
sdk: PushizoSdk;
ready: Ref<boolean>;
error: Ref<string | null>;
subscription: Ref<PushSubscriptionState | null>;
}
export const PushizoKey: InjectionKey<PushizoState> = Symbol('pushizo');
export function createPushizo(options: InitOptions) {
const ready = ref(false);
const error = ref<string | null>(null);
const subscription = ref<PushSubscriptionState | null>(null);
return {
install(app: App) {
app.provide(PushizoKey, { sdk: Pushizo, ready, error, subscription });
if (typeof window === 'undefined') return; // SSR: tarayıcı API'sine dokunma
Pushizo.User.pushSubscription.addObserver((state) => { subscription.value = state; });
Pushizo.init(options)
.then(() => {
ready.value = true;
subscription.value = Pushizo.User.pushSubscription.state;
})
.catch((err: unknown) => { error.value = err instanceof Error ? err.message : String(err); });
},
};
}
export function usePushizo(): PushizoState {
const state = inject(PushizoKey);
if (!state) throw new Error('usePushizo, createPushizo plugin’i kurulmadan kullanılamaz');
return state;
}
```text
```ts
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { createPushizo } from './pushizo';
createApp(App)
.use(
createPushizo({
appId: import.meta.env.VITE_HS_APP_ID,
apiUrl: import.meta.env.VITE_HS_API_URL,
serviceWorkerPath: '/PushizoSDKWorker.js',
allowLocalhostAsSecureOrigin: import.meta.env.DEV,
bell: { enabled: true },
}),
)
.mount('#app');
```text
### Nuxt 3
```ts
// plugins/pushizo.client.ts — yalnızca istemcide çalışır
import { createPushizo } from '~/pushizo';
export default defineNuxtPlugin((nuxtApp) => {
const config = useRuntimeConfig();
nuxtApp.vueApp.use(
createPushizo({
appId: config.public.hsAppId,
apiUrl: config.public.hsApiUrl,
allowLocalhostAsSecureOrigin: import.meta.dev,
}),
);
});
```text
Sunucu tarafında `inject` çağrılan bileşenler için `ready` `false` kalır; SDK'ya dokunan kod `ready` olana kadar çalışmaz.
## 3. İzin ve abonelik
```vue
<script setup lang="ts">
import { computed } from 'vue';
import { usePushizo } from '@/pushizo';
const { sdk, ready, subscription } = usePushizo();
const permission = computed(() => (ready.value ? sdk.Notifications.permission : 'default'));
</script>
<template>
<p v-if="!ready">SDK yükleniyor…</p>
<p v-else-if="permission === 'unsupported'">Bu tarayıcı web push desteklemiyor (HTTPS gerekir).</p>
<p v-else-if="permission === 'denied'">Bildirimler tarayıcı ayarlarından engellenmiş.</p>
<button v-else-if="subscription?.optedIn" type="button" @click="sdk.User.pushSubscription.optOut()">Bildirimleri kapat</button>
<button v-else type="button" @click="sdk.Notifications.requestPermission()">Bildirimlere izin ver</button>
</template>
```text
`permission` değeri `requestPermission` sonrasında abonelik gözlemcisi tetiklenince yeniden hesaplanır (`subscription` değişir).
## 4. Login / logout
```ts
// Pinia store'unuzdaki kullanıcı değişince
import { watch } from 'vue';
import { usePushizo } from '@/pushizo';
const { sdk, ready } = usePushizo();
watch(
[ready, () => auth.user],
([isReady, user]) => {
if (!isReady) return;
if (user) void sdk.login(user.id, user.identityHash); // identity_hash sunucudan (zorunluysa)
else if (sdk.User.externalId) void sdk.logout();
},
{ immediate: true },
);
```text
## 5. Tag, olay ve rota takibi
```ts
sdk.User.addTags({ plan: 'pro' });
sdk.User.removeTag('plan');
sdk.Session.sendEvent('purchase', { sku: 'A1' }, 49.9);
```text
Vue Router ile in-app `screen` tetiği:
```ts
// src/router.ts
router.afterEach((to) => {
const { sdk, ready } = usePushizo();
if (ready.value) sdk.InAppMessages.setScreen(to.name ? String(to.name) : to.path);
});
```text
`usePushizo()` `inject` kullandığından bileşen/`setup` dışında çağrılamaz; router guard'ında `app.runWithContext(() => usePushizo())` ya da plugin'in döndürdüğü state'i modül düzeyinde saklayın.
## 6. Bildirim kutusu bileşeni
```vue
<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue';
import type { InboxItem } from '@pushizo/web';
import { usePushizo } from '@/pushizo';
const { sdk, ready } = usePushizo();
const items = ref<InboxItem[]>([]);
const unread = ref(0);
const loading = ref(false);
const error = ref<string | null>(null);
let stop: (() => void) | null = null;
async function load() {
loading.value = true;
try {
const page = await sdk.Inbox.list({ limit: 20 });
items.value = page.items;
unread.value = page.unreadCount;
error.value = null;
} catch (e) {
error.value = e instanceof Error ? e.message : String(e);
} finally {
loading.value = false;
}
}
async function markRead(id: string) {
const updated = await sdk.Inbox.markRead(id);
items.value = items.value.map((i) => (i.id === id ? updated : i));
}
async function archive(id: string) {
await sdk.Inbox.archive(id);
items.value = items.value.filter((i) => i.id !== id);
}
watch(ready, (r) => { if (r) { void load(); stop = sdk.Inbox.addObserver((e) => { unread.value = e.unreadCount; }); } }, { immediate: true });
onUnmounted(() => stop?.());
</script>
<template>
<section aria-label="Bildirim kutusu">
<h2>Bildirimler ({{ unread }} okunmamış)</h2>
<button type="button" :disabled="loading" @click="load">{{ loading ? 'Yükleniyor…' : 'Yenile' }}</button>
<button type="button" @click="sdk.Inbox.markAllRead().then(load)">Tümünü okundu işaretle</button>
<p v-if="error" role="alert">{{ error }}</p>
<p v-else-if="items.length === 0">Bildirim yok.</p>
<ul v-else>
<li v-for="item in items" :key="item.id" :data-read="item.read">
<strong>{{ item.title ?? '(başlıksız)' }}</strong>
<p v-if="item.body">{{ item.body }}</p>
<a v-if="item.url" :href="item.url">Aç</a>
<button type="button" :disabled="item.read" @click="markRead(item.id)">Okundu</button>
<button type="button" @click="archive(item.id)">Arşivle</button>
</li>
</ul>
</section>
</template>
```text
## 7. Bildirim tıklaması
```ts
onMounted(() => {
const off = sdk.Notifications.addClickListener(({ notification, result }) => {
router.push(result.url ?? notification.url ?? '/');
});
onUnmounted(off);
});
```text
## 8. Sorun giderme
- `window is not defined`: plugin SSR'da `init` çağırıyor; Nuxt'ta dosya adı `.client.ts` olmalı.
- Service worker 404 / abonelik oluşmuyor / bildirim gelmiyor: [Web SDK sorun giderme](/docs/sdk/web#sorun-giderme).
- iOS Safari: [iOS web push](/docs/channels/ios-pwa-web-push).React ile Pushizo Web SDK
@pushizo/web çatıdan bağımsız bir tarayıcı SDK'sıdır; React'te tek bir provider ile başlatılır ve bileşenler bir hook üzerinden SDK'ya ve abonelik durumuna erişir. Bu rehber Create React App / Vite ve Next.js (App…
Angular ile Pushizo Web SDK
@pushizo/web Angular'da bir servis içinde başlatılır (provideAppInitializer), abonelik durumu signal/BehaviorSubject ile bileşenlere akar. Bu rehber standalone bileşen mimarisini (Angular 17+) esas alır; NgModule…