Configurare Landinguri

Crearea paginilor HTML în GC cu AI

1. Ghidul „HTML în 15 minute”

Acest document prezintă procesul complet de creare a unei pagini HTML:

În plus, documentul conține:


2. Workshop-ul „Cum să creezi pagini în GetCourse în 15 minute cu AI”

Prezentarea explică metodologia utilizată pentru generarea paginilor și bunele practici.

Sunt abordate următoarele subiecte:

De asemenea, sunt prezentate exemple practice și demonstrații complete.

Skill-ul pentru widgeturile GetCourse (getcourse-form-css)

Pe lângă ghidurile pentru generarea paginilor HTML, pachetul include și Skill-ul getcourse-form-css, destinat utilizării în Claude.

Acest Skill extinde capabilitățile modelului și îl specializează pentru stilizarea widgeturilor și formularelor din GetCourse.

În loc să explici de fiecare dată cum funcționează widgeturile platformei, Skill-ul oferă deja aceste informații, iar Claude poate genera direct cod CSS compatibil.

Prompturi Utile

Prompturi Utile

PROMPT 1 — Widget GetCourse Modal + Rutarea Butoanelor


Am un landing page HTML de webinar (fișierul e în proiect).
Adaugă modalul GetCourse și rutarea butoanelor fără să modifici designul.

─── CSS (adaugă la sfârșitul blocului <style> existent) ───

.gc-overlay{position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;opacity:0;visibility:hidden;transition:opacity 0.3s ease,visibility 0.3s ease}
.gc-overlay.active{opacity:1;visibility:visible}
.gc-modal{position:relative;background:#fff;border-radius:16px;width:94%;max-width:520px;max-height:90vh;overflow:hidden;transform:translateY(24px) scale(0.97);transition:transform 0.3s ease;box-shadow:0 24px 80px rgba(0,0,0,0.25)}
.gc-overlay.active .gc-modal{transform:translateY(0) scale(1)}
.gc-modal__close{position:absolute;top:12px;right:12px;z-index:2;width:36px;height:36px;border-radius:50%;border:none;background:rgba(0,0,0,0.06);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background 0.2s}
.gc-modal__close:hover{background:rgba(0,0,0,0.12)}
.gc-modal__close svg{width:18px;height:18px;stroke:#333;stroke-width:2.5}
.gc-modal__body{overflow-y:auto;max-height:90vh;-webkit-overflow-scrolling:touch}
.gc-modal__body iframe{display:block;width:100%;min-height:550px;border:none}

─── HTML modal (adaugă imediat înainte de </body>) ───

<div class="gc-overlay" id="gc-overlay" onclick="if(event.target===this)closeGcModal()">
  <div class="gc-modal">
    <button class="gc-modal__close" onclick="closeGcModal()" aria-label="Închide">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </button>
    <div class="gc-modal__body">
      <iframe id="gc-iframe" src="" allow="payment"></iframe>
    </div>
  </div>
</div>

─── Script widget (adaugă după HTML modal) ───

<script>
  (function(){
    var BASE_URL = 'https://edu.inginer.ai';
    var WIDGETS  = { standard: '1610817', vip: '1610799' };
    var STORE_KEY = '__inginer_utms';
    var KEYS = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content'];

    function readFromUrl(){
      var out = {};
      var sp = new URLSearchParams(window.location.search);
      KEYS.forEach(function(k){ var v=sp.get(k); if(v) out[k]=v; });
      var hash = window.location.hash;
      var qi = hash.indexOf('?');
      if(qi !== -1){
        var hsp = new URLSearchParams(hash.slice(qi+1));
        KEYS.forEach(function(k){ var v=hsp.get(k); if(v) out[k]=v; });
      }
      return out;
    }

    function load(){ try{ var s=sessionStorage.getItem(STORE_KEY); return s?JSON.parse(s):{}; }catch(e){ return {}; } }
    function save(o){ try{ sessionStorage.setItem(STORE_KEY,JSON.stringify(o)); }catch(e){} }

    var merged = Object.assign({}, load(), readFromUrl());
    if(Object.keys(merged).length) save(merged);

    window.__getUtms = function(){ return Object.assign({}, load(), readFromUrl()); };

    function buildWidgetUrl(widgetId){
      var utms = window.__getUtms();
      var params = new URLSearchParams(Object.assign({ id: widgetId, ref: window.location.href, loc: window.location.href, clrtQueryData: '1' }, utms));
      return BASE_URL + '/pl/lite/widget/widget?' + params.toString();
    }

    window.openGcModal = function(type){
      var overlay = document.getElementById('gc-overlay');
      var iframe  = document.getElementById('gc-iframe');
      if(!overlay || !iframe) return;
      iframe.src = buildWidgetUrl(WIDGETS[type]);
      overlay.classList.add('active');
      document.body.style.overflow = 'hidden';
    };

    window.closeGcModal = function(){
      var overlay = document.getElementById('gc-overlay');
      var iframe  = document.getElementById('gc-iframe');
      if(!overlay) return;
      overlay.classList.remove('active');
      document.body.style.overflow = '';
      setTimeout(function(){ if(iframe) iframe.src = ''; }, 300);
    };

    document.addEventListener('keydown', function(e){ if(e.key==='Escape') closeGcModal(); });

    window.addEventListener('message', function(event){
      if(!event.origin.includes('edu.inginer.ai')) return;
      if(event.data && typeof event.data==='object' && event.data.type==='resize'){
        var iframe = document.getElementById('gc-iframe');
        if(iframe && event.data.height > 0) iframe.style.height = event.data.height + 'px';
      }
    });
  })();
</script>

─── Rutarea butoanelor ───

Caută toate <button> și <a class="btn"> din fișier și aplică regula:

- Butoane DIN AFARA secțiunii de prețuri:
  onclick="document.getElementById('pricing').scrollIntoView({behavior:'smooth'})"
  (dacă secțiunea de prețuri nu are id="pricing", adaugă-l pe elementul părinte)

- Butonul Standard DIN secțiunea de prețuri:
  onclick="openGcModal('standard')"

- Butonul VIP DIN secțiunea de prețuri:
  onclick="openGcModal('vip')"

Prompturi Utile

PROMPT 2 — Script dată automată + Countdown

Am un landing page HTML de webinar (fișierul e în proiect).
Adaugă scriptul de dată automată și countdown fără să modifici designul.

Reguli:
- Webinarul are loc în fiecare MARȚI la ora 19:00 (ora României), reluarea MIERCURI la 19:00
- Data se calculează dinamic la fiecare vizită — niciodată hardcodată
- Dacă azi e marți dar ora 19:00 a trecut, sare la marțea următoare

Caută în fișier elementele de mai jos și populează-le. Dacă un element nu există, sari peste el.

| ID / selector       | Ce afișează                                              |
|---------------------|----------------------------------------------------------|
| #hero-live-date     | ex: „Marți, 24 iunie", ora 19:00 (ora României)          |
| #hero-reluare-date  | ex: „Reluare: Miercuri, 25 iunie · 19:00"               |
| #live-date          | varianta scurtă cu emoji 📅 și dată bold                 |
| #reluare-date       | varianta scurtă cu emoji 📅 și dată bold                 |
| #micro-live         | linie compactă: dată · 19:00 · 90 minute · sesiune live  |
| #final-cta-date     | dată bold în secțiunea finală de CTA                     |
| .eyebrow.live       | text uppercase: LIVE · DOAR 150 LOCURI · DATA · 19:00    |
| cd-d sau cd-days    | countdown zile (detectează automat ce prefix există)     |
| cd-h sau cd-hours   | countdown ore                                            |
| cd-m sau cd-minutes | countdown minute                                         |
| cd-s sau cd-seconds | countdown secunde                                        |

Scriptul de adăugat (adaptează ID-urile countdown la ce există în fișier):

<script>
  (function(){
    var MONTHS_RO = ['ianuarie','februarie','martie','aprilie','mai','iunie','iulie','august','septembrie','octombrie','noiembrie','decembrie'];
    var DAYS_RO   = ['Duminică','Luni','Marți','Miercuri','Joi','Vineri','Sâmbătă'];

    function getNextTuesday() {
      var now  = new Date();
      var next = new Date(now);
      next.setHours(19, 0, 0, 0);
      var day = now.getDay();
      var daysUntil = (2 - day + 7) % 7;
      if (daysUntil === 0 && now >= next) daysUntil = 7;
      next.setDate(next.getDate() + daysUntil);
      return next;
    }

    function getNextWednesdayAfter(d) {
      var r = new Date(d);
      r.setDate(r.getDate() + 1);
      return r;
    }

    var liveDate    = getNextTuesday();
    var reluareDate = getNextWednesdayAfter(liveDate);

    function fmtShort(d) { return DAYS_RO[d.getDay()] + ', ' + d.getDate() + ' ' + MONTHS_RO[d.getMonth()]; }
    function fmtUpper(d) { return DAYS_RO[d.getDay()].toUpperCase() + ', ' + d.getDate() + ' ' + MONTHS_RO[d.getMonth()].toUpperCase(); }

    var eyebrowEl = document.querySelector('.eyebrow.live');
    if (eyebrowEl) eyebrowEl.textContent = 'LIVE · DOAR 150 LOCURI · ' + fmtUpper(liveDate) + ' · 19:00 (ora României)';

    var heroLiveEl = document.getElementById('hero-live-date');
    if (heroLiveEl) heroLiveEl.innerHTML = '<strong>' + fmtShort(liveDate) + '</strong>, ora 19:00 (ora României)';

    var heroReluareEl = document.getElementById('hero-reluare-date');
    if (heroReluareEl) heroReluareEl.innerHTML = '<strong>Reluare</strong>: ' + fmtShort(reluareDate) + ' · 19:00';

    var microEl = document.getElementById('micro-live');
    if (microEl) microEl.textContent = fmtShort(liveDate) + ' · 19:00 (ora României) · 90 minute · sesiune live';

    var liveDateEl = document.getElementById('live-date');
    if (liveDateEl) liveDateEl.innerHTML = '📅 <strong>' + fmtShort(liveDate) + '</strong> · 19:00';

    var reluareDateEl = document.getElementById('reluare-date');
    if (reluareDateEl) reluareDateEl.innerHTML = '📅 <strong>' + fmtShort(reluareDate) + '</strong> · 19:00';

    var finalCtaEl = document.getElementById('final-cta-date');
    if (finalCtaEl) finalCtaEl.innerHTML = '<strong>' + fmtShort(liveDate) + '</strong>, ora 19:00';

    var target = liveDate.getTime();
    var elD = document.getElementById('cd-d') || document.getElementById('cd-days');
    var elH = document.getElementById('cd-h') || document.getElementById('cd-hours');
    var elM = document.getElementById('cd-m') || document.getElementById('cd-minutes');
    var elS = document.getElementById('cd-s') || document.getElementById('cd-seconds');

    function pad(n) { return String(Math.max(0, n)).padStart(2, '0'); }

    function tick() {
      var diff = target - Date.now();
      if (diff <= 0) diff = 0;
      var s = Math.floor(diff / 1000);
      var d = Math.floor(s / 86400); s -= d * 86400;
      var h = Math.floor(s / 3600);  s -= h * 3600;
      var m = Math.floor(s / 60);    s -= m * 60;
      if (elD) elD.textContent = pad(d);
      if (elH) elH.textContent = pad(h);
      if (elM) elM.textContent = pad(m);
      if (elS) elS.textContent = pad(s);
    }
    tick();
    setInterval(tick, 1000);
  })();
</script>

 

Netlify – Publicarea Landingurilor

Acest articol oferă o prezentare generală a publicării unui landing page pe Netlify și pașii obligatorii folosiți în proiectele noastre.



Pașii obligatorii la publicare

1. Selectarea proiectului

Intri în contul Netlify și alegi site-ul dorit din listă (proiectul pe care vrem să-l actualizăm sau publicăm).

Screenshot 2026-06-30 at 14.58.27.png

2. Dacă site-ul e gol / nefolosit

Intri pe site → secțiunea Project overview → tragi (drag and drop) fișierul HTML dau folderul cu fişiere direct acolo. Pagina e publicată automat.

Screenshot 2026-06-30 at 15.09.48.png

3. Dacă pe site rulează deja o pagină

  • Intri pe site → Deploys;
  • Descarci deployul curent;
  • Adaugi pagina nouǎ în directoriul descǎrcat sau modifici cea existentǎ dacǎ e necesar;
  • Tragi (drag and drop) fișierul nou în zona de Project overview;

Pagina veche este înlocuită cu cea nouă, pe același domeniu/subdomeniu, fără a schimba link-ul.

Screenshot 2026-06-30 at 15.14.34.png

Screenshot 2026-06-30 at 15.15.03.png

4. Revenire la o versiune anterioară

Dacă ceva nu merge bine, din Deploys selectezi un deploy mai vechi din istoric și apeși „Publish deploy” pentru a reveni la el.


Screenshot 2026-06-30 at 15.18.06.png

Screenshot 2026-06-30 at 15.18.29.png

Structura unui Widget

Structura unui Widget

Configurarea obligatorie a widgeturilor pentru Meta Ads (Facebook)

Scop

Orice landing page care urmează să fie promovat prin Meta Ads (Facebook / Instagram) trebuie configurat astfel încât să transmită corect datele către Facebook Conversions API (CAPI).

Înainte de publicarea landing-ului, trebuie adăugate trei componente obligatorii în widget-ul formularului.


Componente obligatorii

În formular trebuie să existe următoarele elemente:

  1. Câmp utilizator – fbclid
  2. Bloc HTML (codul va fi furnizat separat)
  3. Procesul CAPI Facebook corespunzător proiectului

1. Adăugarea câmpului fbclid

În lista componentelor formularului se adaugă un nou câmp utilizator.

Screenshot 2026-06-30 at 11.49.24.png

După adăugare, configurați câmpul astfel:

Câmpul trebuie să fie unul ascuns (hidden), utilizatorul nu trebuie să îl vadă în formular.


2. Adăugarea blocului HTML

În formular se adaugă un widget de tip HTML.

Acesta trebuie poziționat înaintea butonului de trimitere.

În interiorul lui se introduce următorul cod:

<script>
(function () {
  var KEY = 'fm_fbclid';
  var TTL = 90 * 86400000;
  var sp = new URLSearchParams(location.search || '');
  
  // Сначала ищем fbclid напрямую
  var fbclid = sp.get('fbclid');
  
  // Если нет — ищем внутри ref или loc
  if (!fbclid) {
    var ref = sp.get('ref') || sp.get('loc') || '';
    if (ref) {
      var m = ref.match(/fbclid=([^&]+)/);
      if (m) fbclid = m[1];
    }
  }

  if (fbclid) {
    try { localStorage.setItem(KEY, JSON.stringify({ ts: Date.now(), v: fbclid })); } catch(e) {}
  }

  function getStored() {
    try {
      var raw = localStorage.getItem(KEY);
      if (!raw) return null;
      var o = JSON.parse(raw);
      if (!o || !o.ts || Date.now() - o.ts > TTL) return null;
      return o.v || null;
    } catch(e) { return null; }
  }

  function fill() {
    var val = fbclid || getStored();
    if (!val) return;
    document.querySelectorAll('.fbclid input, .fbclid textarea').forEach(function(el) {
      if (!el.value) { el.value = val; }
    });
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', fill);
  } else { fill(); }

  setTimeout(fill, 500);
  setTimeout(fill, 1500);
})();
</script>

3. Adăugarea procesului CAPI Facebook

Din secțiunea Gestionarea formularului se adaugă acțiunea Lansare proces.

Screenshot 2026-06-30 at 11.49.02.png

În funcție de proiectul pentru care se realizează campania, se selectează unul dintre următoarele procese:

Proiect Proces
Manifestare CAPI Facebook
Banii la Treabă CAPI Facebook
Inginer CAPI Facebook Inginer
VibeCoding CAPI Facebook Vibe Coding

Se recomandă păstrarea bifată opțiunea:

capi.png


Verificare înainte de publicare

Înainte ca landing page-ul să intre în publicitate, verificați că sunt îndeplinite toate condițiile:


Exemple de widget-uri configurate

Mai jos sunt câteva exemple de widget-uri care au fost configurate corect și sunt utilizate în producție.

Exemplul 1 – Manifestare
Exemplul 2 – Banii la Treabă
Exemplul 3 – Inginer
Exemplul 4 – Vibe Coding
Structura unui Widget

Widgeturile de înscriere — structură și blocuri de acțiuni

Widgetul este formularul de înscriere de pe landing. Pe lângă câmpurile vizibile, el conține o listă de acțiuni care se execută în ordine, la trimiterea formularului. Articolul descrie ce conține fiecare variantă de widget — Gratuit și VIP — și ce face fiecare bloc.


Widgetul Gratuit

Blocurile, în ordinea în care apar și se execută:

# Bloc Ce face
1 Autorizați utilizatorul Autentifică automat utilizatorul în cont, ca să nu fie nevoit să se logheze manual
2 Lansare proces Pornește procesul descris în articolul Configurarea obligatorie a widgeturilor pentru Meta Ads (Facebook)
3 Creare cerere / comandă Creează comanda pe oferta corespunzătoare
4 Trimite o scrisoare Trimite emailul de confirmare
5 Configurați comanda Se adaugă eticheta, în caz de necesitate
6 Redirecționare Trimite utilizatorul pe pagina de mulțumire

Ce se întâmplă imediat după trimiterea formularului

Restul acțiunilor (creare comandă, configurare, lansare proces) rulează în fundal, în același moment.


Widgetul VIP

Blocurile, în ordinea în care apar și se execută:

# Bloc Ce face
1 Autorizați utilizatorul Autentifică automat utilizatorul în cont
2 Lansare proces Pornește procesul descris în articolul Configurarea obligatorie a widgeturilor pentru Meta Ads (Facebook)
3 Creare cerere / comandă Creează comanda pe oferta VIP
4 Configurați comanda (opțional) Poate fi prezent și aici, dacă e nevoie de adăugarea unei etichete

Diferențele dintre Gratuit și VIP

Widgetul VIP nu conține două blocuri care există la cel gratuit:

Bloc Gratuit VIP
Trimite o scrisoare ✅ Da — emailul pleacă imediat după trimiterea formularului ❌ Nu — widgetul nu expediază email
Redirecționare ✅ Da — utilizatorul ajunge direct pe pagina de mulțumire ❌ Nu — redirectul nu se face din widget

Motivul este că oferta VIP se plătește separat. Utilizatorul nu trebuie dus pe pagina de mulțumire imediat după completarea formularului, ci abia după efectuarea plății, iar emailul de confirmare pleacă tot pe traseul de plată, nu din widget.

Redirect spre pagina de mulțumire pentru ofertele cu plată

Când o ofertă VIP se plătește, utilizatorul trebuie dus, după plată, pe pagina de mulțumire corectă. Legătura dintre ofertă și pagina de mulțumire se configurează într-un bloc de JavaScript din paginile de checkout. Fără această configurare, utilizatorul rămâne pe pagina standard după plată și nu primește instrucțiunile de acces.


Pasul 1 — Adună cele două informații necesare

Pentru fiecare ofertă nouă ai nevoie de:

a) Adresa paginii de mulțumire

Exemplu: https://manifestare.md/webinar-07_08-vip-thx

În cod se folosește doar partea de după domeniu, începând cu /:

/webinar-07_08-vip-thx

b) ID-ul ofertei

Exemplu: 8592956

Screenshot 2026-08-18 at 14.07.29.png


Pasul 2 — Deschide pagina de checkout

Configurarea se face separat pe fiecare școală. Se editează pagina școlii în care se află oferta:

Platformǎ Pagina
Manifestare manifestare.md
Inginer AI edu.inginer.ai
Banii la Treabă edu.baniilatreaba.ro

Pasul 3 — Deschide blocul de JavaScript

În editorul paginii, dă click pe blocul de JavaScript.

Screenshot 2026-08-18 at 14.07.59.png


Pasul 4 — Adaugă oferta în lista de redirecturi

În bloc există obiectul OFFER_REDIRECTS, care leagă fiecare ID de ofertă de pagina ei de mulțumire. Adaugă o linie nouă, după modelul celorlalte:

"8592956": "/webinar-07_08-vip-thx"

Cum arată obiectul după adăugare:

var OFFER_REDIRECTS = {
    "8456396": "/practicum-thx",
    "8499140": "/conferinta-social-media-vip-thx",
    "8549826": "/practicum-thx-august",
    "8592956": "/webinar-07_08-vip-thx"

    // "7174043": "/welcome-intensiv"
};

Reguli de scriere

⚠️ O singură virgulă lipsă strică tot blocul, deci toate redirecturile din pagină încetează să funcționeze, nu doar cel nou adăugat.