Τεκμηρίωση

Το snippet AIDisclose

Εγχειρίδιο διαμόρφωσης και προσαρμογής

Το aidisclose.js είναι το script του ιστότοπου που διαβάζει το manifest ai-disclosure.json σας και εμφανίζει τις γνωστοποιήσεις που απαιτεί ο νόμος: ένα banner αλληλεπίδρασης για chatbots, μια μόνιμη ειδοποίηση περιεχομένου, ορατές ετικέτες σε επισημασμένα μέσα και μηχαναγνώσιμα μεταδεδομένα σελίδας. Δεν έχει εξαρτήσεις, ζυγίζει περίπου 8.2 KB gzipped και πληροί το WCAG 2.1 AA.

Αυτή η σελίδα είναι το πλήρες εγχειρίδιο διαμόρφωσης και προσαρμογής. Για βήματα εγκατάστασης ανά πλατφόρμα (WordPress, Shopify, Webflow, tag managers), δείτε τον οδηγό εγκατάστασης. Μπορείτε επίσης να διαβάσετε αυτό το έγγραφο ως ακατέργαστο Markdown.

Επισκόπηση

Ένα μόνο script tag κινεί τα πάντα. Κατά τη φόρτωση, το snippet ανακτά το manifest σας και έπειτα εμφανίζει μόνο όσα δηλώνει το manifest:

  • Banner αλληλεπίδρασης, για ένα σύστημα conversational: μια ειδοποίηση ότι ο επισκέπτης συνομιλεί με ΤΝ.
  • Ειδοποίηση περιεχομένου, για ένα σύστημα content-generation με scope: site ή scope: page: ένα μικρό μόνιμο chip. Με το κλικ ανοίγει μια σύντομη επεξήγηση με το κείμενο της ειδοποίησης, το όνομα του εκδότη σας και τον σκοπό του συστήματος από το manifest, καθώς και έναν σύνδεσμο προς το αρχείο manifest. Το κείμενο της ειδοποίησης παραπέμπει σε μια επεξήγηση σε απλή γλώσσα στο aidisclose.io. Το σήμα «made by humans» ανοίγει την ίδια κάρτα με το όνομα του εκδότη.
  • Ετικέτες ανά στοιχείο, σε οποιοδήποτε στοιχείο επισημαίνετε με data-ai-content: ένα ορατό σήμα «AI», καθώς και ένα μηχαναγνώσιμο data-digital-source-type.
  • Μεταδεδομένα σελίδας: ένα <link rel="ai-disclosure"> και ένα <meta name="ai-disclosure"> που δείχνουν στο manifest σας.
  • Σήμα «made by humans», όταν το manifest ορίζει noAiDeclared.

Όλα όσα ακολουθούν είναι προαιρετικά. Χωρίς καμία διαμόρφωση, το snippet διαβάζει το /.well-known/ai-disclosure.json σας, εμφανίζεται στη γλώσσα του επισκέπτη σε 28 τοπικές ρυθμίσεις, ακολουθεί τη φωτεινή ή σκοτεινή προτίμηση του λειτουργικού συστήματος και στοιβάζεται πάνω από γνωστές μπάρες συγκατάθεσης για cookies, ώστε οι δύο να μην επικαλύπτονται ποτέ.

Εγκατάσταση

Προσθέστε το tag μία φορά, στο κοινό πρότυπο του ιστότοπού σας, στην κεφαλίδα του θέματος ή στον tag manager, και θα συνοδεύει κάθε σελίδα. Μπορεί να βρίσκεται στο <head> ή οπουδήποτε πριν από το </body>. Είναι deferred, οπότε η θέση του δεν αλλάζει τη συμπεριφορά:

<script src="https://cdn.aidisclose.io/v1/aidisclose.js" defer></script>

Χωρίς attributes, το snippet διαβάζει το manifest στη διεύθυνση https://YOURDOMAIN/.well-known/ai-disclosure.json. Αν η πλατφόρμα σας δεν μπορεί να εξυπηρετήσει ένα αρχείο στη ρίζα του domain, φιλοξενήστε το manifest στο AIDisclose και κατευθύνετε το tag σε αυτό μέσω κλειδιού:

<script src="https://cdn.aidisclose.io/v1/aidisclose.js" data-aidisclose="YOUR_SITE_KEY" defer></script>

Αν το manifest δεν είναι προσβάσιμο, το snippet καταγράφει μια προειδοποίηση στην κονσόλα και δεν εμφανίζει καμία ειδοποίηση βασισμένη στο manifest, ώστε μια αποτυχία ανάκτησης να μην εμφανίζει ποτέ μια εικαζόμενη ειδοποίηση. Τα μεταδεδομένα σελίδας, οι ετικέτες [data-ai-content] σας και ένα banner που επιβάλλεται με data-banner="true" εξακολουθούν να εμφανίζονται.

Διαμόρφωση

Υπάρχουν τρεις τρόποι διαμόρφωσης του snippet. Χρησιμοποιήστε όποιον ταιριάζει στην πλατφόρμα σας.

1. Attributes στο script tag. Ο απλούστερος τρόπος, χωρίς επιπλέον κώδικα:

<script src="https://cdn.aidisclose.io/v1/aidisclose.js"
        data-theme="light" data-lang="fr" defer></script>

2. Ένα καθολικό αντικείμενο διαμόρφωσης. Ορίστε το window.AIDiscloseConfig πριν εκτελεστεί το script. Εκθέτει το πλήρες σύνολο επιλογών, συμπεριλαμβανομένων των επιλογών selector που δεν έχουν μορφή attribute:

<script>
  window.AIDiscloseConfig = {
    theme: 'light',
    mountSelector: '#ai-disclosure-slot',
    triggerSelector: '#chat-launcher',
  };
</script>
<script src="https://cdn.aidisclose.io/v1/aidisclose.js" defer></script>

3. Χειροκίνητη αρχικοποίηση. Προσθέστε data-manual για να αναβάλετε την αυτόματη εκκίνηση και έπειτα καλέστε μόνοι σας το AIDisclose.init() μόλις η εφαρμογή σας είναι έτοιμη (χρήσιμο σε εφαρμογές μίας σελίδας):

<script src="https://cdn.aidisclose.io/v1/aidisclose.js" data-manual defer></script>
<script>
  AIDisclose.init({ theme: 'dark', persistentChip: false });
</script>

Αν υπάρχουν περισσότερες από μία πηγές, υπερισχύει το window.AIDiscloseConfig: παρακάμπτει τόσο τα attributes του script tag όσο και οποιοδήποτε αντικείμενο περνάει στο AIDisclose.init().

Εγχειρίδιο επιλογών

Η επιφάνεια επιλογών είναι σταθερή για τη σειρά 1.x.

Option Attribute Τιμές Προεπιλογή Αποτέλεσμα
theme data-theme light, dark, auto auto Χρωματικό σχήμα. Το auto ακολουθεί την προτίμηση του λειτουργικού συστήματος του επισκέπτη.
siteKey data-aidisclose συμβολοσειρά καμία Φορτώνει το manifest που φιλοξενείται στο AIDisclose για αυτό το κλειδί αντί για το αρχείο well-known.
manifestUrl data-manifest-url URL /.well-known/ai-disclosure.json Διαβάζει το manifest από μια προσαρμοσμένη URL.
lang data-lang κωδικός BCP-47 το <html lang> της σελίδας, αλλιώς η γλώσσα του επισκέπτη Επιβάλλει μια γλώσσα εμφάνισης.
banner data-banner true, false auto Επιβάλλει την ενεργοποίηση ή απενεργοποίηση του banner αλληλεπίδρασης. Αν μείνει αόριστο, εμφανίζεται μόνο όταν το manifest σας δηλώνει ένα σύστημα conversational (chatbot).
persistentChip true, false true Εμφανίζει ή αποκρύπτει το συμπτυγμένο mini-chip του banner αλληλεπίδρασης (το μικρό pill στο οποίο ελαχιστοποιείται).
alwaysShow true, false false Εμφανίζει ξανά το banner σε κάθε επίσκεψη, αγνοώντας την απόρριψη του επισκέπτη (που απομνημονεύεται στο localStorage του προγράμματος περιήγησης).
mountSelector επιλογέας CSS καμία Εμφανίζει το banner ενσωματωμένο μέσα σε αυτό το στοιχείο αντί για το σταθερό overlay στο κάτω μέρος.
triggerSelector επιλογέας CSS καμία Εμφανίζει το banner αλληλεπίδρασης μόνο αφού ο επισκέπτης κάνει κλικ σε αυτό το στοιχείο, όπως έναν εκκινητή συνομιλίας. Σελίδες χωρίς αντίστοιχο στοιχείο δεν εμφανίζουν banner, οπότε ένα chatbot που υπάρχει σε ορισμένες σελίδες γνωστοποιείται μόνο εκεί. Εκκινητές που εισάγονται μετά τη φόρτωση εξακολουθούν να λειτουργούν. Ένας επισκέπτης που απέρριψε νωρίτερα το banner εξακολουθεί να βλέπει το mini-chip.
adjacentSelector επιλογέας CSS καμία Τοποθετεί μια ετικέτα δίπλα σε ένα στοιχείο που δεν μπορείτε να επισημάνετε απευθείας, όπως ένα κλειστό widget ή ένα iframe.
observe true, false true Παρακολουθεί το DOM για περιεχόμενο που προστίθεται αργότερα και το επισημαίνει. Ορίστε false σε πλήρως στατικές σελίδες.
beaconUrl URL καμία Αποστέλλει ένα ανώνυμο beacon {siteKey, flag} σε αξιοσημείωτα συμβάντα. Χωρίς cookies, χωρίς προσωπικά δεδομένα.

Το data-manual δεν είναι τιμή επιλογής: η παρουσία του στο tag αναβάλλει την αυτόματη εκκίνηση ώστε να μπορείτε να καλέσετε μόνοι σας το AIDisclose.init().

Θέμα και εμφάνιση

Ορίστε το ενσωματωμένο σχήμα με το theme (light, dark ή auto). Για να ταιριάξετε ακριβώς με το brand σας, παρακάμψτε τις προσαρμοσμένες ιδιότητες CSS του snippet στο δικό σας stylesheet. Ορίζονται στα .aid-banner, .aid-chip:

Μεταβλητή Ελέγχει
--aid-bg Φόντο
--aid-fg Κείμενο
--aid-line Περίγραμμα
--aid-btn Περίγραμμα κουμπιού απόρριψης
--aid-btnfg Κείμενο κουμπιού απόρριψης
--aid-hov Εφέ hover κουμπιού απόρριψης
.aid-banner, .aid-chip {
  --aid-bg: #0b1020;
  --aid-fg: #e8eaed;
  --aid-line: #2a2f36;
}

Το snippet δεν περιλαμβάνει κανόνες !important και χρησιμοποιεί επιλογείς χαμηλής ειδικότητας, οπότε το δικό σας CSS υπερισχύει. Τα class hooks είναι τα .aid-banner, .aid-chip, .aid-badge, .aid-badge-inline, .aid-wrap, .aid-ai (ειδοποίηση περιεχομένου) και .aid-hm («made by humans»). Επαναπροσαρμόστε απευθείας σε αυτά τα διαστήματα, το στρογγύλεμα γωνιών και τη σκιά.

Από προεπιλογή, το banner είναι ένα σταθερό overlay στο κάτω μέρος του viewport. Ορίστε το mountSelector για να το εμφανίσετε ενσωματωμένο και στατικό μέσα σε ένα στοιχείο που ελέγχετε, ώστε να βρίσκεται μέσα στη δική σας διάταξη.

Προσαρμοσμένη διατύπωση

Το banner και το chip φέρουν ακριβές τοπικοποιημένο κείμενο σε 28 γλώσσες εξ ορισμού. Για να παρακάμψετε τη διατύπωση:

  • Ανά γλώσσα, στο manifest. Προσθέστε disclosure.texts σε ένα σύστημα, με κλειδί τον κωδικό γλώσσας. Το snippet χρησιμοποιεί το κείμενό σας για την αντίστοιχη γλώσσα του επισκέπτη:
{
  "disclosure": {
    "texts": { "en": "Some copy on this page was drafted with AI.", "fr": "Une partie du texte a été rédigée avec de l'IA." }
  }
}
  • Ανά στοιχείο. Προσθέστε data-ai-label σε ένα επισημασμένο στοιχείο για να ορίσετε την ετικέτα εκείνου του σήματος.

Όταν ένα σύστημα ορίζει editorialResponsibility.humanReview: true και το περιεχόμενό του δεν είναι πλήρως παραγόμενο ή χειραγωγημένο από ΤΝ, η ειδοποίηση αναγράφει αυτόματα «υποβοηθούμενο από ΤΝ, ελεγμένο από άνθρωπο» στη γλώσσα του επισκέπτη, αντί για «παραγόμενο από ΤΝ».

Σήμανση του περιεχομένου ΤΝ σας

Το snippet επισημαίνει μόνο όσα εσείς επισημαίνετε. Προσθέστε data-ai-content σε οποιοδήποτε στοιχείο παραγόμενο από ΤΝ:

<img data-ai-content src="/img/generated.webp" alt="…">
<p data-ai-content>AI-drafted summary…</p>
<video data-ai-content src="/clip.mp4"></video>

Κάθε επισημασμένο στοιχείο λαμβάνει ένα ορατό σήμα «AI» και ένα μηχαναγνώσιμο data-digital-source-type (με προεπιλογή trainedAlgorithmicMedia, μια τιμή συμβατή με IPTC και schema.org). Προσθέστε data-ai-label για προσαρμοσμένο κείμενο ετικέτας ή ορίστε μόνοι σας το data-digital-source-type για μεγαλύτερη ακρίβεια.

Για ΤΝ που δεν μπορείτε να επισημάνετε απευθείας, όπως ένα widget συνομιλίας τρίτου μέρους σε ένα κλειστό iframe, χρησιμοποιήστε το adjacentSelector για να τοποθετήσετε μια ετικέτα δίπλα του ή το triggerSelector για να εμφανίσετε το banner αλληλεπίδρασης όταν ανοίγει το widget.

Μια ειδοποίηση παραγωγής περιεχομένου μπορεί να καλύπτει ολόκληρο τον ιστότοπο (disclosure.scope: "site") ή συγκεκριμένες σελίδες (disclosure.scope: "page" με μια λίστα disclosure.pages από path globs, όπως /blog/*). Μια αντιστοίχιση σε επίπεδο σελίδας υπερισχύει έναντι μιας σε επίπεδο ιστότοπου, και ένα σύστημα σε επίπεδο σελίδας χωρίς αντίστοιχη διαδρομή δεν εμφανίζει τίποτα εκεί.

Εφαρμογές μίας σελίδας και frameworks

Το snippet παρακολουθεί το DOM με έναν MutationObserver και επαναξιολογεί την ισχύουσα ειδοποίηση στις αλλαγές διαδρομής, ώστε το περιεχόμενο και οι σελίδες που προστίθενται μετά τη φόρτωση να εξακολουθούν να επισημαίνονται. Σε μια SPA:

  • Διατηρήστε το observe στην προεπιλογή του (true) ώστε να ανιχνεύεται το περιεχόμενο που αποδίδεται από τον client.
  • Αν εξαρτάτε την αρχικοποίηση από την ετοιμότητα της εφαρμογής, προσθέστε data-manual και καλέστε το AIDisclose.init() αφού προσαρτηθεί το framework σας.
  • Οι ειδοποιήσεις σε επίπεδο σελίδας ενημερώνονται αυτόματα καθώς αλλάζει η διαδρομή. Δεν χρειάζεται κλήση ανά διαδρομή.

Ορίστε observe: false μόνο σε πλήρως στατικές σελίδες όπου δεν εισάγεται τίποτα μετά τη φόρτωση.

Content Security Policy

Αν επιβάλλετε μια Content Security Policy, επιτρέψτε ρητά το snippet.

Σημαντικό

Ένα αυστηρό script-src 'self' μπλοκάρει σιωπηλά το snippet του CDN, και οι γνωστοποιήσεις δεν εμφανίζονται ποτέ. Αυτός είναι ο πιο συνηθισμένος λόγος για τον οποίο ένας σωστά δηλωμένος ιστότοπος δεν φτάνει στο Επίπεδο 2.

  • script-src: προσθέστε https://cdn.aidisclose.io ή φιλοξενήστε το aidisclose.js στο δικό σας origin και διατηρήστε το 'self'.
  • style-src: το snippet εισάγει τα στυλ του inline, οπότε το 'unsafe-inline' αρκεί. Αν δεν επιτρέπετε inline στυλ, καταφεύγει στη φόρτωση του aidisclose.css από τον κατάλογο του script, οπότε επιτρέψτε επίσης το https://cdn.aidisclose.io στο style-src (ή φιλοξενήστε αυτό το αρχείο μαζί με το script).
  • connect-src: η ανάκτηση του manifest είναι same-origin για το αρχείο well-known και δεν χρειάζεται τίποτα επιπλέον. Αν φορτώνετε το manifest μέσω κλειδιού, επιτρέψτε το https://cdn.aidisclose.io.

Το manifest ανακτάται χωρίς credentials, οπότε δημοσιεύστε το δημόσια: ένα endpoint που απαιτεί cookies ή ταυτοποίηση δεν θα τα λάβει.

Διαχείριση εκδόσεων και ακεραιότητα

Το CDN εξυπηρετεί τρία κανάλια:

  • Το /v1/aidisclose.js ακολουθεί την τελευταία έκδοση 1.x. Συνιστάται για τους περισσότερους ιστότοπους.
  • Το /v1.0.0/aidisclose.js είναι μια σταθερή, αμετάβλητη έκδοση που μπορείτε να καρφιτσώσετε, με Subresource Integrity:
<script src="https://cdn.aidisclose.io/v1.0.0/aidisclose.js"
        integrity="sha384-…" crossorigin="anonymous" defer></script>
  • Το /latest/aidisclose.js παρακολουθεί πάντα την πιο πρόσφατη έκδοση σε όλες τις κύριες εκδόσεις.

Για να λάβετε το hash SRI που θα καρφιτσώσετε, κάντε build το snippet: το npm run build στο packages/snippet το εκτυπώνει (ο πηγαίος κώδικας είναι ανοικτός στο GitHub).

Δημιουργία του δικού σας UI γνωστοποίησης

Μπορείτε να αποδώσετε το δικό σας UI γνωστοποίησης αντί για το ενσωματωμένο. Δεν υπάρχει ένας μοναδικός διακόπτης απενεργοποίησης: το data-banner="false" και το persistentChip: false αποκρύπτουν μόνο το banner αλληλεπίδρασης και το chip του, ενώ οι ειδοποιήσεις περιεχομένου, τα σήματα [data-ai-content] ανά στοιχείο και το σήμα «made by humans» εξακολουθούν να εμφανίζονται από το manifest και τη σήμανσή σας. Ένα πλήρως προσαρμοσμένο UI σημαίνει να μη βασίζεστε σε αυτά και να αποδίδετε το δικό σας.

Σημείωση

Ο ελεγκτής AIDisclose επαληθεύει την εμφάνιση ανιχνεύοντας τη σήμανση του snippet αναφοράς. Μια πλήρως χειροποίητη γνωστοποίηση είναι έγκυρη, αλλά δεν ανιχνεύεται αυτόματα, οπότε ο ιστότοπος παραμένει στο Επίπεδο 1 (Δηλωμένο) αντί για το Επίπεδο 2 (Εμφανισμένο), εκτός αν η προσαρμοσμένη σήμανσή σας αναπαράγει αυτό που αναζητά ο ελεγκτής. Αν το Επίπεδο 2 έχει σημασία για εσάς, διατηρήστε την ενσωματωμένη εμφάνιση και επαναμορφοποιήστε την με CSS.

Προσβασιμότητα

Το αποδιδόμενο UI πληροί το WCAG 2.1 AA: ορατά περιγράμματα :focus-visible στα διαδραστικά στοιχεία ελέγχου, σωστούς ρόλους και ετικέτες, αντίθεση που διατηρείται σε φωτεινό και σκοτεινό, και κίνηση που περιορίζεται πίσω από το prefers-reduced-motion. Το snippet ανιχνεύει επίσης γνωστές μπάρες συγκατάθεσης για cookies και στοιβάζεται πάνω από αυτές, ώστε οι γνωστοποιήσεις να μην κρύβονται ποτέ πίσω από ένα CMP. Σε πολύ στενές οθόνες, το banner αλληλεπίδρασης ανοίγει ως το συμπαγές chip, ώστε να μην καλύπτει ποτέ το περιεχόμενο.