Widgets — Hanc.AI
5 μορφές1 ετικέτα script14 γλώσσες

Ένας φωνητικός πράκτορας στον ιστότοπό σας.
Μία ετικέτα, χωρίς backend.

Πέντε web components που επιτρέπουν στον επισκέπτη να μιλήσει με τον πράκτορά σας — φωναχτά, μέσα στον περιηγητή, χωρίς εγκατάσταση. Η συνομιλία τρέχει πάνω από WebRTC, η απάντηση έρχεται σε περίπου ένα δευτερόλεπτο, και ο πράκτορας μπορεί να ανοίγει σελίδες και να διαβάζει τι υπάρχει στην οθόνη.

Αυτή η σφαίρα είναι το widget. Πατήστε και μιλήστε.

Πέντε μορφές

Διαλέξτε τη μορφή που χρειάζεται η σελίδα

Ο ίδιος πράκτορας, πέντε τρόποι να τον φτάσετε. Συνδυάστε ελεύθερα — δύο ετικέτες με ένα agent-id είναι συνηθισμένη διάταξη.

Ενσωματωμένη σφαίρα

Ενσωματωμένη σφαίρα

370 px εξ ορισμού, μέσα στη ροή της σελίδας. Δώστε της το πλάτος που θέλετε· σε στενή οθόνη μικραίνει μόνη της.

<hanc-ai-inline-call>

Μια ενότητα σε landing, μια σελίδα επικοινωνίας — όπου η κλήση είναι το νόημα του μπλοκ.

Αιωρούμενη σφαίρα

Αιωρούμενη σφαίρα

120 px, καρφωμένη 32 px από την κάτω δεξιά γωνία. Άλλες τρεις γωνίες στη διάθεσή σας, ή static για να μπει στη ροή.

<hanc-ai-floating-call>

Προσβάσιμη από κάθε σελίδα χωρίς να πιάνει χώρο στη διάταξη.

Χάπι

Χάπι

Ένα οριζόντιο κουμπί: αριστερά μια σφαίρα 48 px, δεξιά η δική σας ετικέτα. Στέκεται στη ροή όπως κάθε άλλο κουμπί.

<hanc-ai-pill-call>

Σε σειρά κουμπιών, στην κεφαλίδα, μέσα σε κάρτα.

Αιωρούμενο χάπι

Αιωρούμενο χάπι

Το ίδιο κουμπί, καρφωμένο 32 px από την κάτω δεξιά γωνία. Οι ίδιες τέσσερις γωνίες στη διάθεσή σας.

<hanc-ai-pill-floating-call>

Όταν η στρογγυλή σφαίρα τραβά υπερβολικά την προσοχή αλλά τη θέλετε πάντα κοντά.

Φόρμα επανάκλησης

Φόρμα επανάκλησης

Επιλογή χώρας, αριθμός που μορφοποιείται καθώς πληκτρολογείται, κι ένα κουμπί. Πόσες φορές θα ξαναγίνει προσπάθεια ορίζεται στον πράκτορα, όχι στο markup.

<hanc-ai-callback>

Για όσους δεν θα μιλήσουν μέσω περιηγητή — και όπου το μικρόφωνο είναι άβολο.

Πέντε λεπτά

Εγκατάσταση

Ένα υποχρεωτικό χαρακτηριστικό: το αναγνωριστικό του πράκτορα από τον πίνακά σας. Κανένα κλειδί API δεν έχει θέση στο markup — ό,τι βρίσκεται στο HTML το βλέπει ο επισκέπτης.

  1. 1

    Πάρτε το αναγνωριστικό του πράκτορα

    Μια συμβολοσειρά τύπου 69d20781de6244c89509eb08, από τον πίνακα.

  2. 2

    Προσθέστε το script

    Μία γραμμή στο <head>. Μέσω npm είναι ένα import — οι ετικέτες δηλώνονται μόνες τους.

  3. 3

    Τοποθετήστε την ετικέτα

    Εκεί που ανήκει η κλήση. Υποχρεωτικό είναι μόνο το agent-id.

  4. 4

    Σερβίρετε μέσω HTTPS

    Οι περιηγητές δεν δίνουν μικρόφωνο σε http://. Όσο αναπτύσσετε, το localhost δουλεύει.

index.html
<!-- 1. the script, once, in <head> -->
<script src="https://unpkg.com/hanc-webrtc-widgets" async></script>

<!-- 2. the widget, wherever the call belongs -->
<hanc-ai-inline-call
  agent-id="69d20781de6244c89509eb08"
  size="320"
  theme="tangerine"
  button-start-text="Talk to us">
</hanc-ai-inline-call>
1 script tag 0 dependencies WebRTC

React

Κάτω από την v19 τα άγνωστα props περνούν ως συμβολοσειρές, οπότε αντικείμενα δεν παραδίδονται έτσι. Τυλίξτε με @lit/react — ο επίσημος δρόμος, που δίνει και τύπους και events.

Next.js

Το widget χρειάζεται περιηγητή: 'use client' και δυναμικό import με ssr: false. Αλλιώς το build σπάει στο server rendering.

Vue

Δουλεύει χωρίς περιτύλιγμα. Πείτε στον bundler ότι οι ετικέτες hanc-ai- είναι custom elements.

Οδηγεί τη σελίδα

Ο πράκτορας μπορεί να ανοίγει σελίδες και να διαβάζει τι υπάρχει στην οθόνη

Η προφορική απάντηση συχνά είναι λάθος μέσο — κανείς δεν θέλει να του διαβάζουν πίνακα παραδόσεων. Γι' αυτό ο πράκτορας μπορεί να στείλει εντολή στη σελίδα και να τη ρωτήσει τι κοιτάζει ο επισκέπτης. Ο έλεγχος μένει στον κώδικά σας: αυτός αποφασίζει τι θα εκτελέσει.

Hanc.AI
navigate
page_context
cart_state
Το widget
navigate

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

page_context

Η σελίδα απαντά πού βρίσκεται ο επισκέπτης και τι εμφανίζεται, ώστε ο πράκτορας να μιλήσει για αυτό το προϊόν και όχι γενικά.

cart_state

Η σελίδα απαντά τι υπάρχει στο καλάθι και πόσο κοστίζει, ώστε ο πράκτορας να πει το σύνολο δυνατά.

Κάθε εντολή φτάνει ως ακυρώσιμο DOM event agent-command. Η κλήση preventDefault() σημαίνει «το χειρίστηκα»· το respond(data) στέλνει απάντηση πίσω στον πράκτορα. Αν αγνοήσετε το event, ο πράκτορας ενημερώνεται ότι δεν χειρίστηκε και επιστρέφει στην ομιλία.

Οι εντολές είναι αιτήματα, όχι διαταγές: ελέγξτε κάθε διαδρομή πριν την ακολουθήσετε. Το παράδειγμα απορρίπτει ό,τι δεν είναι διαδρομή εντός του ιστότοπου.

widget.js
widget.addEventListener('agent-command', (event) => {
  const command = event.detail;

  if (command.type === 'navigate') {
    const path = command.payload?.path;
    // Only same-site paths. Never follow an absolute URL.
    if (!path?.startsWith('/') || path.includes('://')) return;
    event.preventDefault();          // "handled" — the ACK protocol
    router.push(path);
  }

  if (command.type === 'cart_state') {
    event.preventDefault();
    command.respond({                // answer travels back to the agent
      items: cart.map(i => ({ name: i.name, price: i.price })),
      total: cart.total,
      currency: 'UAH',
    });
  }
});

Ζωντανά στο

milotec.com.ua

Ο πράκτορας οδηγεί τον επισκέπτη σε ένα προϊόν, του λέει τι υπάρχει στη σελίδα όπου βρίσκεται και του διαβάζει το καλάθι.

Εφαρμογές κινητού

Το ίδιο widget μέσα στην εφαρμογή σας

iOS και Android το εμφανίζουν και τα δύο σε web view. Φτιάξτε μια μικρή σελίδα HTML στον κώδικα και φορτώστε την με βάση HTTPS — χωρίς ασφαλή προέλευση η μηχανή δεν δίνει μικρόφωνο στη σελίδα.

Ο πράκτορας δεν ακούγεται

Το web view δεν θα αναπαράγει ήχο WebRTC όσο η συνεδρία ήχου της εφαρμογής βρίσκεται σε playback. Γυρίστε τη σε λειτουργία συνομιλίας με έξοδο στο ηχείο για όσο κρατά η κλήση και επαναφέρετέ τη μετά.

Ο πράκτορας απαντά σε λάθος γλώσσα

Το widget παίρνει τη γλώσσα από το navigator.language, που σε ένα web view είναι η γλώσσα του συστήματος, όχι αυτή που επιλέχθηκε στην εφαρμογή. Παρακάμψτε την στην εκκίνηση του εγγράφου — και μπαλώστε το fetch ώστε να προσθέτει browser_language στο αίτημα δωματίου, που το ενσωματωμένο widget δεν στέλνει από μόνο του.

Το μικρόφωνο θέλει και τα δύο μισά

Την άδεια συστήματος για την εφαρμογή και την άδεια για τη σελίδα μέσα στο web view. Στο Android ζητήστε τη συστημική πριν ανοίξει η οθόνη· στο iOS εγκρίνετε το αίτημα της σελίδας στον delegate.

Το ίδιο widget μέσα στην εφαρμογή σας
Ζωντανά στην εφαρμογή RunOrJog
SupportView.swift
let html = """
<hanc-ai-inline-call
    agent-id="\(agentId)"
    support-session-token="\(sessionToken)"></hanc-ai-inline-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async></script>
"""

// An HTTPS base is required — without a secure origin
// the engine will not hand the page a microphone.
webView.loadHTMLString(html, baseURL: URL(string: "https://hanc.ai"))
Ποιος είναι στην κλήση

Αφήστε τον πράκτορα να δει τον συνδεδεμένο χρήστη — και μόνο αυτόν

Περάστε ένα token στο support-session-token. Το widget το επισυνάπτει στην κλήση όπως είναι, εμείς το προωθούμε στο σύστημά σας στην κεφαλίδα X-Hanc-Support-Token, και ο MCP διακομιστής σας αποφασίζει ποιος είναι. Για εμάς το token είναι αδιαφανές: δεν το αναλύουμε, δεν το επαληθεύουμε και δεν το αποθηκεύουμε.

Η εφαρμογή σας
Το widget
Hanc.AI
Το MCP σας
Τα δεδομένα σας

Μην εμπιστεύεστε ποτέ ένα αναγνωριστικό που φτάνει μέσα σε token ως ισχυρισμός. Ρωτήστε τον εκδότη του token ποιος είναι, και δουλέψτε με την απάντηση.

ΠροσέγγισηΠλαστογραφείταιΕτυμηγορία
Ανοιχτό αναγνωριστικόΑσήμαντα εύκολαΑπαράδεκτο
Κρυπτογραφημένο αναγνωριστικόΌχι, αλλά επαναχρησιμοποιείταιΜισή λύση
Token του παρόχου σύνδεσής σαςΌχι: υπογράφει ο πάροχοςΛειτουργεί
Δελτίο διακομιστή μιας χρήσηςΌχι, ούτε επαναχρησιμοποιείταιΤο καλύτερο

Ενεργοποιήστε στη σύνδεση «απαιτείται αναγνωρισμένος συνομιλητής» και σε ανώνυμη κλήση τα εργαλεία σας δεν θα σηκωθούν καθόλου — ο πράκτορας δεν θα μιλήσει για ξένο λογαριασμό ακόμη κι αν αργότερα εμφανιστεί σφάλμα στον κώδικά σας.

Μια κλήση χωρίς token δεν αποκτά καμία πρόσβαση σε λογαριασμό. Αυτή είναι η προεπιλογή, όχι επιλογή.

your_mcp_server.py
async def verified_user_id(ctx) -> str:
    token = ctx.request.headers.get("x-hanc-support-token", "").strip()
    if not token:
        raise ValueError("No signed-in user on this call.")

    # Ask the issuer who this is. Never read the id out of the token.
    resp = await http.get(f"{AUTH_URL}/auth/v1/user",
                          headers={"Authorization": f"Bearer {token}"})
    if resp.status_code != 200:
        raise ValueError("Token invalid or expired.")

    return resp.json()["id"]        # ← the trusted identity
Εμφάνιση

Πρέπει να μοιάζει με τον δικό σας ιστότοπο, όχι με τον δικό μας

Έντεκα θέματα, φωτεινό και σκοτεινό κατά τη ρύθμιση του συστήματος ή εξαναγκασμένα, και άλλα δεκαπέντε περίπου χαρακτηριστικά για την ίδια τη σφαίρα.

default
emerald
rose
amber
cyan
purple
blue
white
black
tangerine
ember
ΧαρακτηριστικόΤι ορίζειΠροεπιλογή
agent-id Ποιος πράκτορας απαντά. Το μόνο υποχρεωτικό
theme Ένα από τα έντεκα χρωματικά θέματα default
size Μέγεθος σε pixel· σε στενές οθόνες μικραίνει μόνο του 370
button-start-text Η ετικέτα του κουμπιού Try to call
position Γωνία για τις αιωρούμενες μορφές bottom-right
glow-intensity Ένταση της λάμψης, 0–2 0.8
audio-reactivity Πόσο έντονα αποκρίνεται η σφαίρα στη φωνή 3.0
terms-enabled Πάνελ συγκατάθεσης πριν την κλήση false
sound-enabled Ήχοι έναρξης και λήξης true
support-session-token Το token του συνδεδεμένου χρήστη

Events για τον δικό σας κώδικα

Κανένα από τα δύο events δεν μεταφέρει δεδομένα: και τα δύο είναι απλό Event, οπότε παίρνετε το γεγονός και τη στιγμή. Περιεχόμενο συνομιλίας δεν υπάρχει σε κανένα από τα δύο — απομαγνητοφωνήσεις και ηχογραφήσεις ζουν στον πίνακα και στο API.

Καθαρές απαντήσεις

Τι σας προστατεύει και τι όχι

Το κανάλι είναι κρυπτογραφημένο

Αιτήματα ελέγχου μέσω HTTPS, ήχος μέσω WSS και SRTP. Χωρίς HTTPS ο περιηγητής ούτως ή άλλως δεν δίνει μικρόφωνο.

Ο πράκτορας ελέγχεται

Κλήση σηκώνεται μόνο για αναγνωριστικό πράκτορα που υπάρχει.

Η πρόσβαση έχει όριο ρυθμού

Η παραχώρηση πρόσβασης στη συνομιλία περιορίζεται, ενάντια σε brute force και κατάχρηση.

Το token συνεδρίας δεν κατακάθεται

Διαβάζεται εκ νέου σε κάθε κλήση και δεν γράφεται ποτέ στη βάση μας.

Η λίστα επιτρεπόμενων domain δεν είναι όριο ασφαλείας

Αυτός ο έλεγχος τρέχει στον περιηγητή. Είναι χρήσιμος ώστε το widget να μην ξεκινήσει κατά λάθος σε αντίγραφο της σελίδας σας, αλλά δεν εμποδίζει κανέναν να καλέσει την υπηρεσία απευθείας. Θεωρήστε δημόσιο ό,τι θα έλεγε ο πράκτορας σε ανώνυμο συνομιλητή, και προστατέψτε τα υπόλοιπα με token συνεδρίας.

Τι μένει και πού

Στον περιηγητή

Δύο εγγραφές στο localStorage: ένας δείκτης επισκέπτη και το γεγονός της συγκατάθεσης

Ήχος

Σε ροή. Ηχογραφείται μόνο αν η ηχογράφηση είναι ενεργή για τον πράκτορα

Απομαγνητοφώνηση

Αποθηκεύεται μαζί με την ηχογράφηση, διαβάζεται στον πίνακα

Τοποθεσία

Επεξεργασία και αποθήκευση στην ΕΕ

Όρια που αξίζει να ξέρετε πριν ξεκινήσετε

Χωρίς HTTPS δεν υπάρχει μικρόφωνο

Δοκιμάστε σε localhost ή ασφαλές domain

Το Safari θέλει χειρονομία πριν τον ήχο

Η κλήση πρέπει να ξεκινά από κλικ

Blockers και proxy μπορεί να κόψουν το WebRTC

Κρατήστε τη φόρμα επανάκλησης ως εναλλακτική

Σε ιδιωτικό παράθυρο δεν μένει δείκτης

Κάθε συνομιλία μοιάζει με την πρώτη — είναι φυσιολογικό

Το React κάτω από 19 δεν περνά αντικείμενα ως χαρακτηριστικά

Τυλίξτε με @lit/react

Το server rendering σπάει με απευθείας import

Δυναμικό import με ssr: false

Το τηλέφωνό σας, επιτέλους
δουλεύει για εσάς.

Ξεκινήστε δωρεάν σε 60 δευτερόλεπτα. Χωρίς πιστωτική κάρτα. Ακυρώστε οποτεδήποτε. Απλώς το τηλέφωνο να απαντά μόνο του.

Book a Meeting