Add HeaderAdBanner component to ChatView, FeedbackView, and PartnersView
- Integrated HeaderAdBanner into ChatView.vue, FeedbackView.vue, and PartnersView.vue to enhance advertising capabilities. - Updated PartnersView.vue to include a new app branding structure for improved visual hierarchy. These changes collectively improve the user interface and advertising integration across multiple views.
This commit is contained in:
130
ADSENSE.md
Normal file
130
ADSENSE.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# AdSense in SingleChat
|
||||
|
||||
## Ziel
|
||||
|
||||
Im Header kann ein Google-AdSense-Banner eingeblendet werden. Die Einbindung ist bereits vorbereitet, aber nur aktiv, wenn die passenden Vite-Variablen gesetzt sind.
|
||||
|
||||
## Bereits im Code vorbereitet
|
||||
|
||||
- Header-Komponente: [HeaderAdBanner.vue](/mnt/share/torsten/Programs/SingleChat/client/src/components/HeaderAdBanner.vue)
|
||||
- Einbindung in die Kopfzeilen:
|
||||
- [ChatView.vue](/mnt/share/torsten/Programs/SingleChat/client/src/views/ChatView.vue)
|
||||
- [PartnersView.vue](/mnt/share/torsten/Programs/SingleChat/client/src/views/PartnersView.vue)
|
||||
- [FeedbackView.vue](/mnt/share/torsten/Programs/SingleChat/client/src/views/FeedbackView.vue)
|
||||
|
||||
Aktiv wird der Banner nur mit:
|
||||
|
||||
- `VITE_ADSENSE_CLIENT`
|
||||
- `VITE_ADSENSE_HEADER_SLOT`
|
||||
|
||||
## Was bei Google AdSense erledigt werden muss
|
||||
|
||||
### 1. AdSense-Konto und Website
|
||||
|
||||
In AdSense selbst:
|
||||
|
||||
1. Website `ypchat.net` hinzufügen
|
||||
2. Eigentum/Einbindung abschließen
|
||||
3. Warten, bis die Website von Google geprüft und freigegeben wurde
|
||||
|
||||
Ohne freigegebene Website werden in der Regel keine regulären Anzeigen ausgeliefert.
|
||||
|
||||
### 2. Anzeigenblock anlegen
|
||||
|
||||
Für den Header in AdSense einen normalen responsiven Display-Anzeigenblock anlegen.
|
||||
|
||||
Benötigt werden daraus:
|
||||
|
||||
- Publisher-ID
|
||||
Beispiel: `ca-pub-1234567890123456`
|
||||
- Slot-ID des Header-Anzeigenblocks
|
||||
Beispiel: `1234567890`
|
||||
|
||||
### 3. `ads.txt` korrekt pflegen
|
||||
|
||||
AdSense erwartet in der Regel einen korrekten Eintrag in `/ads.txt`.
|
||||
|
||||
Für Google AdSense ist das Format typischerweise:
|
||||
|
||||
```txt
|
||||
google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0
|
||||
```
|
||||
|
||||
Wichtig:
|
||||
|
||||
- `pub-...` muss zu deinem echten AdSense-Konto passen
|
||||
- die Datei muss öffentlich unter `https://ypchat.net/ads.txt` erreichbar sein
|
||||
- Änderungen brauchen oft etwas Zeit, bis Google sie erkennt
|
||||
|
||||
Im Projekt liegt aktuell eine Datei unter [docroot/ads.txt](/mnt/share/torsten/Programs/SingleChat/docroot/ads.txt). Diese muss auf deine echte Publisher-ID geprüft und ggf. angepasst werden.
|
||||
|
||||
## Was im Projekt erledigt werden muss
|
||||
|
||||
### 1. Vite-Variablen setzen
|
||||
|
||||
In der Projekt-`.env` die beiden Werte ergänzen:
|
||||
|
||||
```env
|
||||
VITE_ADSENSE_CLIENT=ca-pub-1234567890123456
|
||||
VITE_ADSENSE_HEADER_SLOT=1234567890
|
||||
```
|
||||
|
||||
Hinweis:
|
||||
|
||||
- `VITE_...` ist notwendig, damit die Werte im Client verfügbar sind
|
||||
- ohne diese Werte bleibt der Banner automatisch unsichtbar
|
||||
|
||||
### 2. Frontend neu bauen
|
||||
|
||||
Nach Änderung der `.env`:
|
||||
|
||||
```bash
|
||||
cd client
|
||||
npm run build
|
||||
```
|
||||
|
||||
Danach wie bisher den Build nach `docroot/dist` deployen.
|
||||
|
||||
### 3. Server/Deployment aktualisieren
|
||||
|
||||
Je nach Deploy-Prozess:
|
||||
|
||||
1. neuen Client-Build deployen
|
||||
2. prüfen, dass `docroot/dist` aktuell ist
|
||||
3. Service neu starten oder Deployment neu laden
|
||||
|
||||
## Prüfung nach dem Deploy
|
||||
|
||||
### Technisch
|
||||
|
||||
Prüfen:
|
||||
|
||||
- ist im HTML ein AdSense-Script geladen?
|
||||
- erscheint im Header ein reservierter Anzeigenbereich?
|
||||
- gibt es Fehler in der Browser-Konsole?
|
||||
|
||||
### Extern
|
||||
|
||||
Prüfen:
|
||||
|
||||
- `https://ypchat.net/ads.txt` ist erreichbar
|
||||
- AdSense zeigt keinen `ads.txt`-Fehler mehr
|
||||
- die Website ist in AdSense als bereit/freigegeben markiert
|
||||
|
||||
## Wichtige Hinweise
|
||||
|
||||
- Im lokalen Development erscheinen AdSense-Anzeigen oft nicht sinnvoll oder gar nicht.
|
||||
- Nach dem ersten Einbau kann es dauern, bis Google echte Anzeigen ausliefert.
|
||||
- Wenn Header-Anzeigen die UX zu stark stören, sollte der Banner auf Mobile ausgeblendet bleiben. Das ist im Code bereits berücksichtigt.
|
||||
- Für Consent-/CMP-Themen kann je nach Land eine zusätzliche Einwilligungslösung nötig sein. Das ist aktuell nicht Teil dieser Implementierung.
|
||||
|
||||
## Kurz-Checkliste
|
||||
|
||||
1. In AdSense Website hinzufügen und freigeben lassen.
|
||||
2. Header-Display-Ad-Unit anlegen.
|
||||
3. Publisher-ID und Slot-ID notieren.
|
||||
4. `docroot/ads.txt` auf korrekten Google-Eintrag prüfen.
|
||||
5. `.env` mit `VITE_ADSENSE_CLIENT` und `VITE_ADSENSE_HEADER_SLOT` ergänzen.
|
||||
6. Client neu bauen.
|
||||
7. Deployen.
|
||||
8. Live prüfen, ob `ads.txt` und Banner korrekt ausgeliefert werden.
|
||||
80
client/src/components/HeaderAdBanner.vue
Normal file
80
client/src/components/HeaderAdBanner.vue
Normal file
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div v-if="isEnabled" class="header-ad-banner">
|
||||
<ins
|
||||
ref="adElement"
|
||||
class="adsbygoogle"
|
||||
style="display:block"
|
||||
:data-ad-client="adClient"
|
||||
:data-ad-slot="adSlot"
|
||||
data-ad-format="auto"
|
||||
data-full-width-responsive="true"
|
||||
></ins>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, nextTick, onMounted, ref } from 'vue';
|
||||
|
||||
const adElement = ref(null);
|
||||
const adClient = import.meta.env.VITE_ADSENSE_CLIENT || '';
|
||||
const adSlot = import.meta.env.VITE_ADSENSE_HEADER_SLOT || '';
|
||||
const isEnabled = computed(() => Boolean(adClient && adSlot));
|
||||
|
||||
function ensureAdSenseScript() {
|
||||
if (!isEnabled.value) return;
|
||||
if (document.querySelector('script[data-adsense-loader="true"]')) return;
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${adClient}`;
|
||||
script.crossOrigin = 'anonymous';
|
||||
script.dataset.adsenseLoader = 'true';
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (!isEnabled.value) return;
|
||||
|
||||
ensureAdSenseScript();
|
||||
await nextTick();
|
||||
|
||||
try {
|
||||
// Avoid duplicate initialization on remount.
|
||||
if (adElement.value?.dataset.adsInitialized === 'true') return;
|
||||
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
||||
if (adElement.value) {
|
||||
adElement.value.dataset.adsInitialized = 'true';
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('AdSense Banner konnte nicht initialisiert werden:', error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header-ad-banner {
|
||||
flex: 1;
|
||||
min-width: 280px;
|
||||
max-width: 728px;
|
||||
margin: 0 16px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.header-ad-banner :deep(ins) {
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.header-ad-banner {
|
||||
min-width: 220px;
|
||||
max-width: 468px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.header-ad-banner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -8,6 +8,7 @@
|
||||
<h1>Chat</h1>
|
||||
</div>
|
||||
</div>
|
||||
<HeaderAdBanner />
|
||||
<div v-if="chatStore.isLoggedIn" class="header-status">
|
||||
<span class="header-status-chip">{{ chatStore.userName }}</span>
|
||||
<span v-if="chatStore.isoCountryCode" class="header-status-chip">{{ chatStore.isoCountryCode }}</span>
|
||||
@@ -89,6 +90,7 @@ import SearchView from '../components/SearchView.vue';
|
||||
import InboxView from '../components/InboxView.vue';
|
||||
import HistoryView from '../components/HistoryView.vue';
|
||||
import ImprintContainer from '../components/ImprintContainer.vue';
|
||||
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
|
||||
|
||||
const chatStore = useChatStore();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<h1>Feedback</h1>
|
||||
</div>
|
||||
</div>
|
||||
<HeaderAdBanner />
|
||||
</header>
|
||||
|
||||
<FeedbackPanel />
|
||||
@@ -18,5 +19,6 @@
|
||||
|
||||
<script setup>
|
||||
import FeedbackPanel from '../components/FeedbackPanel.vue';
|
||||
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
|
||||
import ImprintContainer from '../components/ImprintContainer.vue';
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div class="chat-container">
|
||||
<header class="header">
|
||||
<h1>SingleChat</h1>
|
||||
<div class="app-brand">
|
||||
<span class="app-brand-mark">S</span>
|
||||
<div class="app-brand-copy">
|
||||
<span class="app-brand-eyebrow">SingleChat</span>
|
||||
<h1>Partner</h1>
|
||||
</div>
|
||||
</div>
|
||||
<HeaderAdBanner />
|
||||
</header>
|
||||
|
||||
<MenuBar />
|
||||
@@ -36,6 +43,7 @@ import axios from 'axios';
|
||||
import { useRouter } from 'vue-router';
|
||||
import MenuBar from '../components/MenuBar.vue';
|
||||
import UserList from '../components/UserList.vue';
|
||||
import HeaderAdBanner from '../components/HeaderAdBanner.vue';
|
||||
import ImprintContainer from '../components/ImprintContainer.vue';
|
||||
import { useChatStore } from '../stores/chat';
|
||||
|
||||
@@ -52,4 +60,3 @@ onMounted(async () => {
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user