Vista previa
Código para insertar
Pega el código en el lugar de tu página donde debe aparecer el quiz.
Bueno saber
- Si tu web usa una Content Security Policy, añade en script-src: https://www.qwissit.com
- El widget no usa cookies ni guarda nada en el navegador. Solo carga el script y las preguntas desde Qwissit.
- Las preguntas cambian automáticamente. Para cambiar colores o textos, genera aquí un código nuevo y sustituye el anterior.
Opcional: inserción a través de tu propio dominio
Si no quieres solicitudes a servidores de terceros, tu servidor web entrega el quiz: reenvía una ruta como /qwissit/ a Qwissit. El navegador de tus visitantes solo habla con tu dominio y Qwissit solo ve la dirección de tu servidor. La inserción directa de arriba sigue siendo la opción sencilla por defecto.
1. Configura tu servidor web: reenvía /qwissit/ a https://www.qwissit.com/widget/v1/, sin cookies, dirección IP ni otros datos de tus visitantes.
nginx
location ^~ /qwissit/ {
proxy_pass https://www.qwissit.com/widget/v1/;
proxy_set_header Host www.qwissit.com;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For "";
proxy_set_header X-Real-IP "";
proxy_set_header Cookie "";
proxy_set_header Referer "";
proxy_set_header User-Agent "qwissit-proxy";
proxy_hide_header Set-Cookie;
}Apache (mod_proxy, mod_ssl, mod_headers)
SSLProxyEngine On
<Location "/qwissit/">
ProxyPass "https://www.qwissit.com/widget/v1/"
ProxyAddHeaders Off
RequestHeader unset Cookie
RequestHeader unset Referer
RequestHeader set User-Agent "qwissit-proxy"
Header unset Set-Cookie
</Location>Caddy
handle_path /qwissit/* {
rewrite * /widget/v1{path}?{query}
reverse_proxy https://www.qwissit.com {
header_up Host {upstream_hostport}
header_up -X-Forwarded-For
header_up -Cookie
header_up -Referer
header_up User-Agent qwissit-proxy
header_down -Set-Cookie
}
}PHP (Shared Hosting)
¿Sin acceso a la configuración del servidor (hosting compartido)? Descarga el archivo PHP, guárdalo como qwissit-proxy.php en tu carpeta web y usa /qwissit-proxy.php/qwissit-widget.js como dirección del script. Solo reenvía los archivos del widget.
2. Sustituye la dirección del script en el código de arriba:
<script src="/qwissit/qwissit-widget.js" async></script>
3. Prueba: la llamada con tu dominio debe devolver 200 y content-type: text/javascript. Un 404 apunta a un punto de «Si no funciona»; una página HTML indica que tu CMS se ha quedado con la solicitud.
curl -I https://example.org/qwissit/qwissit-widget.js
Después, en el navegador con las herramientas de desarrollo (F12), pestaña «Red»: no debe aparecer ninguna solicitud a www.qwissit.com.
Si no funciona
- nginx devuelve 404: las reglas para archivos estáticos como location ~* \.(js|css)$ tienen prioridad sobre las reglas de prefijo simples, y nginx busca qwissit-widget.js en tu servidor. Por eso el fragmento dice location ^~ /qwissit/: el ^~ garantiza que esta ruta siempre se reenvíe.
- Los cambios solo surten efecto tras recargar: nginx -t && nginx -s reload; en Apache, apachectl configtest && systemctl reload apache2. En Docker, con un archivo de configuración montado por separado, el contenedor sigue viendo la versión antigua después de sustituir el archivo (rsync, cp); entonces solo ayuda reiniciar el contenedor (docker compose restart <servicio>).
- Apache: los módulos proxy, proxy_http, ssl y headers deben estar activos (a2enmod proxy proxy_http ssl headers). Las reglas van en la configuración del servidor o del VirtualHost, no en el .htaccess. Si solo puedes usar .htaccess, usa el archivo PHP.
- Archivo PHP: debe estar de verdad en la carpeta web (en TYPO3, en public/); si no, el CMS se queda con la solicitud. El servidor debe pasar a PHP la ruta que sigue al archivo (PATH_INFO): en Apache AcceptPathInfo On (por defecto en muchos hostings), en nginx en la regla de PHP así:
location ~ \.php(/|$) { fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; # … your usual fastcgi_pass / include fastcgi_params }
Opcional: comprobar resultados a prueba de manipulación
¿Quieres registrar en tu web que alguien ha superado el quiz, por ejemplo para marcar una lección o dar puntos? Entonces deja que Qwissit confirme el resultado. Así nadie puede falsearlo.
Cómo funciona
- Tu página da al quiz un código de un solo uso y lo recuerda.
- El visitante resuelve el quiz. Qwissit comprueba cada respuesta; las preguntas falladas vuelven hasta que todas estén bien.
- Al final, tu página recibe un justificante que solo Qwissit puede emitir y lo envía a tu servidor.
- Tu servidor pregunta a Qwissit si el justificante es auténtico y corresponde a tu código y a tu quiz. Solo entonces guarda el resultado.
Qué tienes que añadir
Dos sitios, ambos en PHP. Tus visitantes deben haber iniciado sesión, porque el resultado tiene que pertenecer a alguien.
A) En la página del quiz: Este bloque sustituye al fragmento normal. Ajusta data-set y data-course a tu quiz; los valores están en el código de arriba.
<?php
session_start(); // your visitors are signed in
$nonce = $_SESSION['quiz_nonce']['http'] ??= rtrim(strtr(base64_encode(random_bytes(16)), '+/', '-_'), '=');
?>
<div id="quiz" data-qwissit-widget data-set="12" data-course="13" data-lang="de"
data-verify="<?= $nonce ?>"></div>
<script src="https://www.qwissit.com/widget/v1/qwissit-widget.js" async></script>
<script>
document.getElementById('quiz').addEventListener('qwissit:finish', function (e) {
if (!e.detail.passed || !e.detail.token) return;
fetch('quiz-complete.php', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'lesson=http&token=' + encodeURIComponent(e.detail.token)
}).then(function (r) {
if (r.ok) { /* done: e.g. show a tick */ }
});
});
</script>
B) Un archivo nuevo quiz-complete.php en la misma carpeta. Pon en QUIZZES los mismos valores de set y course y guarda el resultado en la línea marcada como convenga a tu web.
<?php
// quiz-complete.php – checks the result with Qwissit and saves it only if everything matches
session_start();
const QUIZZES = ['http' => ['set' => 12, 'course' => 13]]; // same values as data-set / data-course
$lesson = (string)($_POST['lesson'] ?? '');
$token = (string)($_POST['token'] ?? '');
$quiz = QUIZZES[$lesson] ?? null;
$nonce = (string)($_SESSION['quiz_nonce'][$lesson] ?? '');
if (!$quiz || $nonce === '' || $token === '') { http_response_code(400); exit; }
$ch = curl_init('https://www.qwissit.com/widget/v1/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['token' => $token]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 4,
]);
$r = json_decode((string)curl_exec($ch), true);
curl_close($ch);
if (!is_array($r)) { http_response_code(503); exit; } // Qwissit not reachable: save nothing
if (($r['valid'] ?? false) !== true
|| !hash_equals($nonce, (string)($r['nonce'] ?? ''))
|| (int)$r['set'] !== $quiz['set'] || (int)$r['course'] !== $quiz['course']) {
http_response_code(403); exit; // forged, already used, expired or another quiz
}
unset($_SESSION['quiz_nonce'][$lesson]); // the code counts only once
// ▶ save the result here, e.g. user + $lesson + date (+ $r['wrong'] = failed attempts)
header('Content-Type: application/json');
echo json_encode(['ok' => true]);
El archivo solo guarda si Qwissit confirma el justificante, este pertenece a tu código de un solo uso y procede del quiz correcto. Después el código queda gastado, así que cada resultado cuenta una sola vez. Si ahora no se puede contactar con Qwissit, no se guarda nada: deja que el visitante lo intente más tarde. El justificante vale una hora.
Conviene saber
- ¿Por qué el rodeo por tu servidor? El widget también comunica el final del quiz directamente en el navegador (evento qwissit:finish), pero cualquiera con algo de conocimientos técnicos puede lanzarlo por su cuenta. Basta para mostrar algo, no para puntos, certificados o desbloqueos.
- Muestra el quiz con código solo a visitantes con sesión iniciada y no crees sesiones para los demás; si no, cada bot crea una.
- Protege quiz-complete.php como tus otros formularios: comprueba el inicio de sesión, acepta solo solicitudes de tu propio sitio y limita el número de solicitudes.
- Tras un éxito, el visitante recibe un código nuevo en la siguiente visita y puede repetir el quiz.
- Para probar: un justificante inventado, el mismo justificante por segunda vez y el de otro quiz deben rechazarse.
Texto para tu política de privacidad
Una propuesta que puedes adaptar a tu sitio. No sustituye el asesoramiento jurídico.
Insertado directamente
En este sitio web insertamos un quiz de Qwissit (www.qwissit.com). Al cargarlo, tu navegador obtiene el script y las preguntas de www.qwissit.com; con ello se transmite tu dirección IP. El quiz no usa cookies, no guarda nada en tu navegador y no almacena tus respuestas. La base jurídica es nuestro interés legítimo en una oferta de aprendizaje interactiva (art. 6.1.f RGPD). Más información: https://www.qwissit.com/en/privacy#widget
A través de tu propio dominio (proxy)
En este sitio web insertamos un quiz de Qwissit. Nuestro propio servidor entrega el script y las preguntas, que obtiene de Qwissit. Tu navegador no se conecta con Qwissit, y Qwissit no recibe ni tu dirección IP ni cookies ni otros datos sobre ti. El quiz no usa cookies, no guarda nada en tu navegador y no almacena tus respuestas. Más información: https://www.qwissit.com/en/privacy#widget