, so that
* hubspotform.js (which only loads later, inside the body, on pages that
* actually have a HubSpot Form component) can read the same values
* without duplicating them. hubspotform.js reads this lazily (at init
* time, not at parse time) so it never depends on this script having run
* first -- treat that as defense-in-depth, not a reason to relax this
* script's own placement in
.
*/
window.HS_CONFIG = window.HS_CONFIG || Object.freeze({
PORTAL_ID: '24131897',
GPC_FORM_GUID: '2b423b38-65e9-4811-8fdc-85e52e7d29d8',
DEFAULT_REGION: 'na1'
});
const PORTAL_ID = window.HS_CONFIG.PORTAL_ID;
const GPC_FORM_GUID = window.HS_CONFIG.GPC_FORM_GUID;
// ---------- Generic cookie helpers ----------
function getCookie(name) {
const match = document.cookie.match(
new RegExp('(^|;\\s*)' + name.replace(/[.*+?^{}()|[\]\\$]/g, '\\$&') + '=([^;]*)')
);
return match ? decodeURIComponent(match[2]) : null;
}
function setCookie(name, value, days) {
const expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + expires + '; path=/; SameSite=Lax; Secure;';
}
// ---------- OptanonConsent parsing ----------
//
// OptanonConsent is a URL-encoded, semi-structured query string, e.g.:
// isGpcEnabled=1&datestamp=2026-09-11T14:32:10Z&version=202401.1.0&
// groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1%2CC0004%3A0&...
//
// Note: OneTrust's cookie format has changed across versions -- verify
// field names against your account's actual cookie before relying on
// this in prod.
function parseOptanonConsent() {
const raw = getCookie('OptanonConsent');
if (!raw) return null;
const params = new URLSearchParams(raw);
const groupsRaw = params.get('groups') || '';
const groups = {};
groupsRaw.split(',').forEach((pair) => {
const parts = pair.split(':');
const id = parts[0];
const status = parts[1];
if (id) groups[id] = status === '1';
});
return {
isGpcEnabled: params.get('isGpcEnabled') === '1',
datestamp: params.get('datestamp'),
groups: groups
};
}
// ---------- Status tracking cookie (keyed by email) ----------
//
// Keyed by email rather than a single flat record. On a shared device, a
// flat "last status sent" record gets overwritten by whoever used the
// browser most recently, causing one person's status to look "already
// sent" for someone else. Keying by email keeps each person's dedupe
// state separate even on a shared browser/cookie jar.
const STATUS_COOKIE_NAME = 'hs_gpc_status_records';
const STATUS_COOKIE_DAYS = 365;
function normalizeEmail(email) {
return String(email || '').trim().toLowerCase();
}
function getAllStatusRecords() {
const raw = getCookie(STATUS_COOKIE_NAME);
if (!raw) return {};
try {
return JSON.parse(raw) || {};
} catch (e) {
return {};
}
}
function getStatusRecordForEmail(email) {
const key = normalizeEmail(email);
if (!key) return null;
return getAllStatusRecords()[key] || null;
}
function setStatusRecordForEmail(email, lastSentGpcStatus, submissionStatus) {
const key = normalizeEmail(email);
if (!key) return;
const records = getAllStatusRecords();
records[key] = {
lastSentGpcStatus: lastSentGpcStatus,
lastUpdated: new Date().toISOString(),
submissionStatus: submissionStatus // "submitted" | "failed" | "pending"
};
// Cookies have a ~4KB practical limit -- prune oldest entries beyond a
// reasonable count so this doesn't grow unbounded on shared devices.
const MAX_RECORDS = 20;
const keys = Object.keys(records);
if (keys.length > MAX_RECORDS) {
const oldestFirst = keys.sort(
(a, b) => new Date(records[a].lastUpdated) - new Date(records[b].lastUpdated)
);
oldestFirst.slice(0, keys.length - MAX_RECORDS).forEach((k) => delete records[k]);
}
setCookie(STATUS_COOKIE_NAME, JSON.stringify(records), STATUS_COOKIE_DAYS);
}
// ---------- Email-identified submission path (preferred) ----------
async function maybeSubmitGpcStatusForEmail(email) {
const key = normalizeEmail(email);
if (!key) return;
const consent = parseOptanonConsent();
if (!consent) return; // OneTrust hasn't initialized yet
const currentGpcStatus = consent.isGpcEnabled === true;
const existing = getStatusRecordForEmail(key);
if (
existing &&
existing.lastSentGpcStatus === currentGpcStatus &&
existing.submissionStatus === 'submitted'
) {
return; // Already recorded this exact status for this specific person
}
setStatusRecordForEmail(key, currentGpcStatus, 'pending');
try {
await submitGpcStatusUpdate({ email: key, gpcStatus: currentGpcStatus });
setStatusRecordForEmail(key, currentGpcStatus, 'submitted');
} catch (err) {
setStatusRecordForEmail(key, currentGpcStatus, 'failed');
}
}
// ---------- hubspotutk-only background path (fallback, higher risk) ----------
//
// Browser-identified, not person-identified -- can misattribute status on
// a genuinely shared device. Kept as a fallback for visitors who never
// submit a form.
const HUBSPOTUTK_RETRY_ATTEMPTS = 5;
const HUBSPOTUTK_RETRY_DELAY_MS = 1000;
async function maybeSubmitGpcStatusBackground(retriesLeft = HUBSPOTUTK_RETRY_ATTEMPTS) {
const hubspotutk = getCookie('hubspotutk');
if (!hubspotutk) {
// hubspotutk is written by HubSpot's own tracking script, which only runs
// (and sets this cookie) after it processes the _hsq doNotTrack push from
// syncHubSpotDoNotTrack — it may not exist yet the instant consent
// resolves. Retry for a bounded window rather than giving up on one miss.
if (retriesLeft > 0) {
setTimeout(() => maybeSubmitGpcStatusBackground(retriesLeft - 1), HUBSPOTUTK_RETRY_DELAY_MS);
}
return;
}
const consent = parseOptanonConsent();
if (!consent) return;
const currentGpcStatus = consent.isGpcEnabled === true;
const dedupeKey = 'hutk:' + hubspotutk;
const existing = getStatusRecordForEmail(dedupeKey);
if (
existing &&
existing.lastSentGpcStatus === currentGpcStatus &&
existing.submissionStatus === 'submitted'
) {
return;
}
setStatusRecordForEmail(dedupeKey, currentGpcStatus, 'pending');
try {
await submitGpcStatusUpdate({ hubspotutk: hubspotutk, gpcStatus: currentGpcStatus });
setStatusRecordForEmail(dedupeKey, currentGpcStatus, 'submitted');
} catch (err) {
setStatusRecordForEmail(dedupeKey, currentGpcStatus, 'failed');
}
}
async function submitGpcStatusUpdate(opts) {
const email = opts.email;
const hubspotutk = opts.hubspotutk;
const gpcStatus = opts.gpcStatus;
const fields = [
{ name: 'consent_optout_gpc', value: String(gpcStatus) },
{ name: 'consent_last_updated_date_gpc', value: new Date().toISOString() }
];
if (email) fields.push({ name: 'email', value: email });
const response = await fetch(
'https://api.hsforms.com/submissions/v3/integration/submit/' + PORTAL_ID + '/' + GPC_FORM_GUID,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
fields: fields,
context: hubspotutk ? { hutk: hubspotutk } : {}
})
}
);
if (!response.ok) throw new Error('HubSpot form submission failed: ' + response.status);
return response.json();
}
// Kept as a defensive fallback in case this account's OneTrust setup does
// dispatch it in some configurations — doesn't hurt to also listen.
function onOneTrustGroupsUpdated() {
maybeSubmitGpcStatusBackground();
}
window.addEventListener('OneTrustGroupsUpdated', onOneTrustGroupsUpdated);
if (window.OneTrust) {
// Fast path for when consent is already known (e.g. on a refresh, or a
// returning visitor) — avoids waiting on an event that may not fire again
// if consent isn't changing this load.
maybeSubmitGpcStatusBackground();
}
// ---------- HubSpot form submission hooks (email-identified, preferred) ----------
// Iframe embed (postMessage-based) -- also covers hbspt.forms.create(),
// since that renders the same underlying iframe and fires the same
// postMessage events.
window.addEventListener('message', (event) => {
if (!event.data || event.data.type !== 'hsFormCallback') return;
if (event.data.eventName !== 'onFormSubmitted') return;
const email = event.data.data && event.data.data.submissionValues
? event.data.data.submissionValues.email
: null;
if (email) {
maybeSubmitGpcStatusForEmail(email);
} else {
maybeSubmitGpcStatusBackground();
}
});
// HubSpot's non-iframe ("raw HTML") / v4 forms dispatch this CustomEvent
// on window. event.detail only carries { formId, instanceId } -- actual
// field values must be fetched via the async getFormFieldValues() call.
window.addEventListener('hs-form-event:on-submission:success', (event) => {
if (!window.HubSpotFormsV4) return;
HubSpotFormsV4.getFormFromEvent(event)
.getFormFieldValues()
.then((fieldValues) => {
// "0-1" is HubSpot's fixed objectTypeId for Contact -- forms with
// fields on multiple objects (e.g. Contact + Ticket) can have more
// than one "email" field, so target the Contact's explicitly.
const emailField = fieldValues.find((field) => field.name === '0-1/email');
const email = emailField ? emailField.value : null;
if (email) {
maybeSubmitGpcStatusForEmail(email);
} else {
maybeSubmitGpcStatusBackground();
}
});
});
})();
El Mapa de carreras profesionales ayuda a determinar las opciones que pueden ser buenas opciones para ti:
Los seis grupos generales de carreras profesionales en el borde exterior consisten en varias áreas profesionales que comparten tareas laborales similares
Las ocupaciones se agrupan en 26 áreas profesionales
Las ocupaciones están codificadas de color según tus respuestas de los inventarios
¡Analiza a detalle tus principales opciones de carrera profesional para obtener más información!
La foto instantánea de carreras profesionales te proporciona todo lo que necesitas saber sobre tus principales opciones de carrera profesional, que incluye:
°ä²¹°ù²¹³¦³Ù±ð°ùòõ³Ù¾±³¦²¹²õ&²Ô²ú²õ±è;
Salario proyectado potencial
Capacitación y materias recomendadas de la escuela secundaria
Detalles sobre las tareas laborales, el entorno laboral, las oportunidades de desarrollo profesional
La búsqueda de carreras profesionales en MyACT te permite filtrar tu búsqueda por:
Palabras clave
�rea profesional obtenida del mapa de carreras profesionales
Nivel de ingresos
Carrera universitaria
Nivel de educación
¿Estás listo para comenzar tus inventarios?Â
Inicia sesión o crea una cuenta MyACT para empezar a explorar.
This action will open a new window. Do you want to proceed?
Welcome to ACT
If you are accessing this site from outside the United States, Puerto Rico, or U.S. Territories, please proceed to the non-U.S. version of our website.