📖 Documentație

Integrează AceEngine
pe orice site în 5 minute

Un singur <script> adaugă un asistent AI pe site-ul tău. Funcționează cu orice tehnologie — fără backend propriu, fără chei OpenAI expuse.

⚡ Quickstart

Adaugă un singur tag <script> înainte de </body> și gata. Înlocuiește LIC-XXXX cu cheia ta din Dashboard.

HTML
<!-- Adaugă înainte de </body> -->
<script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX"></script>
Widget-ul apare automat în colțul dreapta-jos. Indexarea conținutului paginii pornește în background imediat după încărcare.
ℹ️ Cheia ta API o găsești în Dashboard → Licențele tale. Fiecare licență este legată de un singur domeniu.

🔍 Cum funcționează

  • 1
    Script încărcat — browserul descarcă ace.js de pe serverele AceEngine.
  • 2
    Validare licență — cheia este validată server-side față de domeniul autorizat. Dacă nu coincide, widget-ul nu pornește.
  • 3
    Config fetch — widget-ul descarcă culorile, titlul și setările White Label configurate în Dashboard.
  • 4
    Indexare pagină — conținutul HTML al paginii curente este trimis la AceEngine, chuncat, embeddtat vectorial și stocat pentru RAG.
  • 5
    Chat activ — fiecare mesaj al vizitatorului declanșează un RAG search + răspuns GPT bazat exclusiv pe conținutul site-ului tău.

HTML / Vanilla JS

Cea mai simplă integrare — funcționează pe orice site static sau generat server-side.

HTML

index.html
<!DOCTYPE html>
<html lang="ro">
<head>
  <meta charset="UTF-8">
  <title>Site-ul meu</title>
</head>
<body>

  <!-- conținutul tău -->

  <!-- AceEngine — înainte de </body> -->
  <script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX"></script>

</body>
</html>

React / Next.js

Folosește un useEffect pentru a injecta script-ul o singură dată la mount-ul componentei root.

React App.jsx / Layout.jsx

JSX
import { useEffect } from 'react';

export default function Layout({ children }) {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX';
    script.async = true;
    document.body.appendChild(script);

    return () => document.body.removeChild(script);
  }, []);

  return <>{children}</>;
}

Next.js App Router — layout.tsx

TSX
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Script
          src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
ℹ️ În Next.js folosește strategy="afterInteractive" pentru a nu bloca hydration-ul. Evită strategy="beforeInteractive".

Vue / Nuxt

Vue 3 App.vue

Vue
<script setup>
import { onMounted, onUnmounted } from 'vue';

let script;

onMounted(() => {
  script = document.createElement('script');
  script.src = 'https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX';
  document.body.appendChild(script);
});

onUnmounted(() => script?.remove());
</script>

<template>
  <RouterView />
</template>

Nuxt 3 nuxt.config.ts

TypeScript
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX',
          defer: true,
          body: true
        }
      ]
    }
  }
})

Angular

Angular Varianta 1 — index.html (simplă)

HTML
<!-- src/index.html — înainte de </body> -->
<script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX" defer></script>

Angular Varianta 2 — AppComponent (programatic)

TypeScript
import { Component, OnInit } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Inject } from '@angular/core';

@Component({ selector: 'app-root', templateUrl: './app.component.html' })
export class AppComponent implements OnInit {

  constructor(@Inject(DOCUMENT) private document: Document) {}

  ngOnInit() {
    const s = this.document.createElement('script');
    s.src = 'https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX';
    s.defer = true;
    this.document.body.appendChild(s);
  }
}

WordPress

Există 3 metode — recomandăm wp_enqueue_scripts prin functions.php pentru control maxim.

WordPress Metoda 1 — functions.php (recomandat)

PHP
// Adaugă în wp-content/themes/TEMA-TA/functions.php

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script(
        'aceengine',
        'https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX',
        [],
        null,
        true  // true = încarcat în footer, înainte de </body>
    );
});

WordPress Metoda 2 — Plugin Header & Footer Scripts

Plugin: Insert Headers and Footers
<!-- Settings → Insert Headers and Footers → Scripts in Footer -->
<script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX" defer></script>

WordPress Metoda 3 — Elementor / Page Builder

În Elementor Pro: Site Settings → Custom Code → Add Code → Location: Body End și lipește tag-ul <script> de mai sus.

Webflow / Wix / Squarespace

Webflow

  • 1
    Deschide Project Settings → Custom Code
  • 2
    În secțiunea Footer Code, lipește tag-ul <script>
  • 3
    Click Save Changes și publică site-ul

Wix

  • 1
    Din Editor, click Settings → Custom Code
  • 2
    Click + Add Custom Code
  • 3
    Lipește tag-ul, selectează Body — end, aplică pe All pages
⚠️ Wix necesită plan Premium pentru a adăuga cod custom.

Squarespace

  • 1
    Mergi la Settings → Advanced → Code Injection
  • 2
    În câmpul Footer, lipește tag-ul <script>
  • 3
    Click Save

ASP.NET Core / Razor

Razor _Layout.cshtml

Razor / HTML
<!-- Views/Shared/_Layout.cshtml — înainte de </body> -->

<script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX"
        asp-append-version="false"></script>

Razor Dezactivare pe Development

Razor
<environment exclude="Development">
    <script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key=LIC-XXXX"></script>
</environment>
ℹ️ Tag-ul <environment exclude="Development"> face widget-ul invizibil în development și activ doar în Staging/Production.

Laravel / PHP

Laravel layouts/app.blade.php

Blade
<!-- resources/views/layouts/app.blade.php — înainte de </body> -->

@unless(app()->isLocal())
    <script src="https://ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net/api/ace.js?key={{ config('aceengine.key') }}"
            defer></script>
@endunless

Laravel config/aceengine.php

PHP
<?php
// config/aceengine.php
return [
    'key' => env('ACEENGINE_KEY', ''),
];
.env
ACEENGINE_KEY=LIC-XXXX

⚙️ Configurare widget

Widget-ul preia automat configurarea din Dashboard (White Label). Opțional, poți suprascrie setările direct în pagină prin obiectul global window.AceConfig definit înainte de tag-ul <script>.

JavaScript
<!-- Înainte de tag-ul ace.js -->
<script>
  window.AceConfig = {
    title:       'Asistent AI',        // titlul din header widget
    placeholder: 'Cum te pot ajuta?',  // placeholder input
    primaryColor:'#7c3aed',             // culoare principală
    position:    'bottom-right',       // 'bottom-right' | 'bottom-left'
    language:    'ro',                 // 'ro' | 'en'
    showBranding:false,                // ascunde "Powered by AceEngine"
  };
</script>
<script src="...ace.js?key=LIC-XXXX"></script>
Proprietate Default Descriere
title"Asistent AI"Titlul afișat în header-ul widget-ului
placeholder"Scrie o întrebare..."Textul placeholder din câmpul de input
primaryColor"#7c3aed"Culoarea principală (hex). Afectează butonul, header, link-uri
position"bottom-right"Poziția butonului flotant: bottom-right sau bottom-left
language"ro"Limba interfeței: ro (română) sau en (engleză)
showBrandingtrueAfișează / ascunde "Powered by AceEngine" (disponibil pe planul Pro+)

📡 Evenimente JS

Widget-ul emite evenimente custom pe window pe care le poți asculta pentru integrări avansate (analytics, CRM, tracking).

JavaScript
// Widget deschis
window.addEventListener('ace:open', () => {
  console.log('Widget deschis');
});

// Widget închis
window.addEventListener('ace:close', () => {
  console.log('Widget închis');
});

// Mesaj trimis de user
window.addEventListener('ace:message', (e) => {
  console.log('Întrebare:', e.detail.question);
});

// Răspuns primit de la AI
window.addEventListener('ace:response', (e) => {
  console.log('Răspuns AI:', e.detail.answer);
});

// Eroare (licență invalidă, rată depășită etc.)
window.addEventListener('ace:error', (e) => {
  console.error('Eroare AceEngine:', e.detail.message);
});
ace:open
Declanșat când userul deschide widget-ul. Fără detalii suplimentare.
ace:close
Declanșat când userul închide widget-ul.
ace:message
e.detail.question — textul întrebării trimise de user.
ace:response
e.detail.answer — răspunsul complet generat de AI.
ace:error
e.detail.message — mesajul de eroare. e.detail.code — codul HTTP (401, 429 etc.)

Exemplu — Google Analytics 4

JavaScript
window.addEventListener('ace:message', (e) => {
  gtag('event', 'ace_question', {
    event_category: 'AceEngine',
    event_label:    e.detail.question.substring(0, 100)
  });
});

🔧 Troubleshooting

❌ Widget-ul nu apare deloc
🔍 Cauze posibile: cheia API lipsește sau e greșită în URL-ul scriptului; domeniul site-ului nu coincide cu cel din licență; script-ul e blocat de Content Security Policy (CSP).
✅ Fix: Verifică cheia în Dashboard. Verifică că domeniul din licență este exact https://site-ul-tau.com (fără slash final). Deschide Console în DevTools și caută erori cu prefixul [AceEngine].
❌ "License validation failed: 403"
🔍 Domeniul din care se face request-ul nu coincide cu cel autorizat în licență. Apare frecvent pe localhost în development.
✅ Fix: Adaugă o licență separată cu domeniul localhost pentru development sau folosește tag-ul <environment exclude="Development"> în ASP.NET / @unless(app()->isLocal()) în Laravel pentru a dezactiva pe local.
❌ Widget apare dar nu răspunde la întrebări
🔍 Conținutul site-ului nu a fost indexat încă. Indexarea se face automat la primul load al fiecărei pagini — poate dura câteva secunde.
✅ Fix: Navighează pe câteva pagini ale site-ului, așteaptă 30 de secunde și încearcă din nou. Dacă problema persistă, verifică că domeniul nu e blocat în robots.txt.
❌ "Rate limit exceeded: 429"
🔍 Ai depășit limita lunară de requesturi a planului tău.
✅ Fix: Upgrade la un plan superior din Dashboard → Billing. Limita se resetează în prima zi a lunii.
❌ Script blocat de Content Security Policy
🔍 Site-ul tău are un header CSP strict care blochează scripturi externe.
✅ Fix: Adaugă domeniul AceEngine în directiva script-src a CSP-ului tău:
Content-Security-Policy: script-src 'self' ludoprogrammingaceengine-dwb8bdexfnbzdvd2.northeurope-01.azurewebsites.net
❌ Widget apare de două ori (SPA navigation)
🔍 Script-ul a fost injectat de mai multe ori în aplicațiile SPA la fiecare navigare de rută.
✅ Fix: Adaugă o verificare înainte de injectare:
if (!document.querySelector('[src*="ace.js"]')) { /* injectează */ }

❓ FAQ

Funcționează pe mai multe pagini ale aceluiași site?
Da. Adaugă script-ul în layout-ul global și va fi activ pe toate paginile. Fiecare pagină vizitată este indexată automat și adăugată în baza de cunoștințe a asistentului.
Pot folosi aceeași cheie pe mai multe domenii?
Nu. Fiecare licență este legată de un singur domeniu, din motive de securitate. Creează licențe separate pentru fiecare domeniu din Dashboard. Poți crea oricâte licențe ai nevoie în limita planului.
Ce se întâmplă dacă depășesc limita de requesturi?
Widget-ul afișează un mesaj de eroare vizitatorilor până la resetarea limitei (prima zi a lunii). Nu există întrerupere a site-ului — doar funcționalitatea AI este oprită temporar. Recomandăm upgrade-ul preventiv dacă te apropii de limită.
Conținutul site-ului meu este trimis la OpenAI?
Conținutul paginilor tale este procesat de serverele AceEngine și stocat vectorial pentru RAG. Interogările utilizatorilor sunt trimise la OpenAI în forma procesată. Nu stocăm date personale ale vizitatorilor — nu există logging de conversații asociate cu identitate.
Pot personaliza aspectul widget-ului?
Da. Din Dashboard → White Label poți configura titlul, culorile și logo-ul. Pe planul Pro+ poți ascunde branding-ul "Powered by AceEngine". Poți suprascrie și local prin obiectul window.AceConfig descris în secțiunea de configurare.
Funcționează pe site-uri cu conținut dinamic (SPA)?
Da, cu mențiunea că indexarea se face la nivel de pagină vizitată. Într-un SPA, conținutul render-at client-side este capturat după ce DOM-ul e complet. Dacă conținutul se încarcă lazy (după scroll), acesta s-ar putea să nu fie indexat complet — soluția este un sitemap.xml complet care permite crawling-ul server-side.
Cât timp durează până apare conținutul nou în răspunsuri?
Indexarea unei pagini durează sub 5 secunde după ce este vizitată prima dată. Conținutul nou publicat apare în răspunsuri la prima accesare a paginii respective. Crawler-ul automat re-indexează periodic paginile modificate.

Nu ai găsit răspunsul?

Contactează-ne →