aidisclose.js는 ai-disclosure.json 매니페스트를 읽어 법이 요구하는 공개를 표시하는 온사이트 스크립트입니다: 챗봇을 위한 상호작용 배너, 상시 콘텐츠 고지, 표시된 미디어의 가시적 라벨, 기계 판독 가능 페이지 메타데이터. 의존성이 없고, gzip 압축 시 약 8.2 KB이며, WCAG 2.1 AA를 충족합니다.
이 페이지는 전체 구성 및 커스터마이징 레퍼런스입니다. 플랫폼별 설치 단계(WordPress, Shopify, Webflow, 태그 관리자)는 설치 안내를 참고하세요. 이 문서는 원본 markdown으로도 읽을 수 있습니다.
개요
스크립트 태그 하나가 모든 것을 구동합니다. 로드 시 스니펫은 매니페스트를 가져온 다음, 매니페스트가 선언한 것만 표시합니다:
- 상호작용 배너,
conversational시스템의 경우: 방문자가 AI와 대화하고 있다는 고지. - 콘텐츠 고지,
scope: site또는scope: page가 지정된content-generation시스템의 경우: 작은 상시 칩. 클릭하면 고지 텍스트, 매니페스트의 게시자 이름과 시스템 용도, 매니페스트 파일 링크를 담은 간단한 설명이 열립니다. 고지 텍스트는 aidisclose.io의 평이한 언어 설명으로 연결됩니다. "made by humans" 배지는 게시자 이름과 함께 동일한 카드를 엽니다. - 요소별 라벨,
data-ai-content로 표시한 모든 요소에 적용됩니다: 가시적인 "AI" 배지와 기계 판독 가능한data-digital-source-type. - 페이지 메타데이터: 매니페스트를 가리키는
<link rel="ai-disclosure">와<meta name="ai-disclosure">. - "Made by humans" 배지, 매니페스트가
noAiDeclared를 설정한 경우.
아래의 모든 내용은 선택 사항입니다. 구성이 없으면 스니펫은 /.well-known/ai-disclosure.json을 읽고, 28개 로케일에 걸쳐 방문자의 언어로 표시하며, 운영 체제의 라이트 또는 다크 설정을 따르고, 알려진 쿠키 동의 바 위에 쌓여 둘이 겹치지 않도록 합니다.
설치
태그를 사이트의 공유 템플릿, 테마 헤더, 또는 태그 관리자에 한 번 추가하면 모든 페이지에 함께 배포됩니다. <head> 안이나 </body> 앞 어디에도 둘 수 있습니다. deferred 방식이므로 배치 위치가 동작을 바꾸지 않습니다:
<script src="https://cdn.aidisclose.io/v1/aidisclose.js" defer></script>
속성이 없으면 스니펫은 https://YOURDOMAIN/.well-known/ai-disclosure.json의 매니페스트를 읽습니다. 플랫폼이 도메인 루트에서 파일을 제공할 수 없다면, 매니페스트를 AIDisclose에 호스팅하고 태그가 키로 이를 가리키도록 하세요:
<script src="https://cdn.aidisclose.io/v1/aidisclose.js" data-aidisclose="YOUR_SITE_KEY" defer></script>
매니페스트에 도달할 수 없으면 스니펫은 콘솔 경고를 기록하고 매니페스트 기반 고지를 표시하지 않으므로, 가져오기 실패가 추측성 고지를 보여주는 일은 없습니다. 페이지 메타데이터, [data-ai-content] 라벨, 그리고 data-banner="true"로 강제된 배너는 여전히 표시됩니다.
구성
스니펫을 구성하는 방법에는 세 가지가 있습니다. 플랫폼에 맞는 방식을 사용하세요.
1. 스크립트 태그의 속성. 추가 코드가 필요 없는 가장 간단한 방법입니다:
<script src="https://cdn.aidisclose.io/v1/aidisclose.js"
data-theme="light" data-lang="fr" defer></script>
2. 전역 구성 객체. 스크립트가 실행되기 전에 window.AIDiscloseConfig를 정의하세요. 속성 형태가 없는 선택자 옵션을 포함한 전체 옵션 집합을 제공합니다:
<script>
window.AIDiscloseConfig = {
theme: 'light',
mountSelector: '#ai-disclosure-slot',
triggerSelector: '#chat-launcher',
};
</script>
<script src="https://cdn.aidisclose.io/v1/aidisclose.js" defer></script>
3. 수동 초기화. data-manual을 추가해 자동 시작을 미룬 다음, 앱이 준비되면 직접 AIDisclose.init()를 호출하세요(싱글 페이지 앱에서 유용합니다):
<script src="https://cdn.aidisclose.io/v1/aidisclose.js" data-manual defer></script>
<script>
AIDisclose.init({ theme: 'dark', persistentChip: false });
</script>
두 개 이상의 소스가 존재하면 window.AIDiscloseConfig가 우선합니다: 스크립트 태그 속성과 AIDisclose.init()에 전달된 객체를 모두 재정의합니다.
옵션 레퍼런스
옵션 표면은 1.x 계열에서 안정적입니다.
| Option | Attribute | Values | Default | Effect |
|---|---|---|---|---|
theme |
data-theme |
light, dark, auto |
auto |
색 구성표. auto는 방문자의 OS 설정을 따릅니다. |
siteKey |
data-aidisclose |
문자열 | 없음 | well-known 파일 대신 이 키에 해당하는 AIDisclose 호스팅 매니페스트를 로드합니다. |
manifestUrl |
data-manifest-url |
URL | /.well-known/ai-disclosure.json |
커스텀 URL에서 매니페스트를 읽습니다. |
lang |
data-lang |
BCP-47 코드 | 페이지 <html lang>, 없으면 방문자의 언어 |
표시 언어를 강제합니다. |
banner |
data-banner |
true, false |
auto | 상호작용 배너를 강제로 켜거나 끕니다. 설정하지 않으면 매니페스트가 conversational(챗봇) 시스템을 선언할 때만 표시됩니다. |
persistentChip |
— | true, false |
true |
상호작용 배너가 접혔을 때의 미니 칩(최소화 시 나타나는 작은 알약 모양)을 표시하거나 숨깁니다. |
alwaysShow |
— | true, false |
false |
방문자의 닫기(브라우저 localStorage에 기억됨)를 무시하고 방문할 때마다 배너를 다시 표시합니다. |
mountSelector |
— | CSS 선택자 | 없음 | 고정된 하단 오버레이 대신 이 요소 안에 배너를 인라인으로 표시합니다. |
triggerSelector |
— | CSS 선택자 | 없음 | 방문자가 채팅 실행기 같은 이 요소를 클릭한 후에만 상호작용 배너를 표시합니다. 일치하는 요소가 없는 페이지에서는 배너가 표시되지 않으므로, 일부 페이지에만 존재하는 챗봇은 그곳에서만 공개됩니다. 로드 후에 삽입된 실행기도 동작합니다. 앞서 배너를 닫은 방문자에게는 여전히 미니 칩이 표시됩니다. |
adjacentSelector |
— | CSS 선택자 | 없음 | 닫힌 위젯이나 iframe처럼 직접 표시할 수 없는 요소 옆에 라벨을 배치합니다. |
observe |
— | true, false |
true |
나중에 추가되는 콘텐츠를 감지하기 위해 DOM을 관찰하고 라벨을 붙입니다. 완전히 정적인 페이지에서는 false로 설정하세요. |
beaconUrl |
— | URL | 없음 | 주목할 만한 이벤트 발생 시 익명의 {siteKey, flag} 비컨을 전송합니다. 쿠키도, 개인 데이터도 없습니다. |
data-manual은 옵션 값이 아닙니다: 태그에 존재하면 자동 시작을 미뤄 직접 AIDisclose.init()를 호출할 수 있게 합니다.
테마와 외관
내장 구성표는 theme(light, dark, auto)으로 설정합니다. 브랜드에 정확히 맞추려면 자체 스타일시트에서 스니펫의 CSS 커스텀 속성을 재정의하세요. 이 속성들은 .aid-banner, .aid-chip에 정의되어 있습니다:
| Variable | Controls |
|---|---|
--aid-bg |
배경 |
--aid-fg |
텍스트 |
--aid-line |
테두리 |
--aid-btn |
닫기 버튼 테두리 |
--aid-btnfg |
닫기 버튼 텍스트 |
--aid-hov |
닫기 버튼 호버 |
.aid-banner, .aid-chip {
--aid-bg: #0b1020;
--aid-fg: #e8eaed;
--aid-line: #2a2f36;
}
스니펫은 !important 규칙을 두지 않고 낮은 명시도의 선택자를 사용하므로, 여러분의 CSS가 우선합니다. 클래스 후크는 .aid-banner, .aid-chip, .aid-badge, .aid-badge-inline, .aid-wrap, .aid-ai(콘텐츠 고지), .aid-hm("made by humans")입니다. 이들에 직접 간격, 모서리 반경, 그림자를 다시 지정하세요.
기본적으로 배너는 뷰포트 하단에 고정된 오버레이입니다. mountSelector를 설정하면 여러분이 제어하는 요소 안에 인라인 정적 방식으로 배너를 표시하여 자체 레이아웃 안에 자리 잡게 할 수 있습니다.
커스텀 문구
배너와 칩은 28개 언어로 정확한 현지화 텍스트를 기본 제공합니다. 문구를 재정의하려면:
- 언어별로, 매니페스트에서. 시스템에 언어 코드를 키로 하는
disclosure.texts를 추가하세요. 스니펫은 방문자의 언어와 일치하는 텍스트를 사용합니다:
{
"disclosure": {
"texts": { "en": "Some copy on this page was drafted with AI.", "fr": "Une partie du texte a été rédigée avec de l'IA." }
}
}
- 요소별로. 표시된 요소에
data-ai-label을 추가해 해당 배지의 라벨을 설정하세요.
시스템이 editorialResponsibility.humanReview: true를 설정하고 그 콘텐츠가 완전히 AI로 생성되거나 조작된 것이 아닐 때, 고지는 방문자의 언어로 "AI-generated" 대신 자동으로 "AI-assisted, human-reviewed"로 표시됩니다.
AI 콘텐츠 표시
스니펫은 여러분이 표시한 것만 라벨링합니다. AI로 생성된 요소에 data-ai-content를 추가하세요:
<img data-ai-content src="/img/generated.webp" alt="…">
<p data-ai-content>AI-drafted summary…</p>
<video data-ai-content src="/clip.mp4"></video>
표시된 각 요소는 가시적인 "AI" 배지와 기계 판독 가능한 data-digital-source-type(기본값은 IPTC 및 schema.org 호환 값인 trainedAlgorithmicMedia)를 받습니다. 커스텀 라벨 텍스트가 필요하면 data-ai-label을 추가하거나, 더 구체적으로 지정하려면 data-digital-source-type를 직접 설정하세요.
닫힌 iframe 안의 서드파티 채팅 위젯처럼 직접 주석을 달 수 없는 AI의 경우, adjacentSelector로 그 옆에 라벨을 배치하거나 triggerSelector로 위젯이 열릴 때 상호작용 배너를 표시하세요.
콘텐츠 생성 고지는 사이트 전체(disclosure.scope: "site")나 특정 페이지(/blog/* 같은 경로 글로브 목록인 disclosure.pages와 함께 지정한 disclosure.scope: "page")를 다룰 수 있습니다. 페이지 범위 일치가 사이트 범위보다 우선하며, 일치하는 경로가 없는 페이지 범위 시스템은 그곳에서 아무것도 표시하지 않습니다.
싱글 페이지 앱과 프레임워크
스니펫은 MutationObserver로 DOM을 관찰하고 라우트 변경 시 적용 가능한 고지를 재평가하므로, 로드 후에 추가된 콘텐츠와 페이지도 라벨링됩니다. SPA에서는:
- 클라이언트 렌더링 콘텐츠가 포착되도록
observe를 기본값(true)으로 유지하세요. - 앱 준비 상태에 따라 초기화를 제어한다면
data-manual을 추가하고 프레임워크가 마운트된 후AIDisclose.init()를 호출하세요. - 페이지 범위 고지는 라우트가 바뀌면 자동으로 갱신됩니다. 라우트마다 호출할 필요가 없습니다.
observe: false는 로드 후에 아무것도 삽입되지 않는 완전히 정적인 페이지에서만 설정하세요.
콘텐츠 보안 정책
콘텐츠 보안 정책을 적용한다면 스니펫을 명시적으로 허용하세요.
중요
엄격한 script-src 'self'는 CDN 스니펫을 조용히 차단하며, 공개는 전혀 표시되지 않습니다. 이는 올바르게 선언된 사이트가 Level 2에 도달하지 못하는 가장 흔한 이유입니다.
script-src:https://cdn.aidisclose.io를 추가하거나,aidisclose.js를 자체 오리진에서 셀프 호스팅하고'self'를 유지하세요.style-src: 스니펫은 스타일을 인라인으로 삽입하므로'unsafe-inline'이면 충분합니다. 인라인 스타일을 허용하지 않으면 스크립트 디렉터리에서aidisclose.css를 로드하는 방식으로 대체되므로,style-src에도https://cdn.aidisclose.io를 허용하세요(또는 해당 파일을 스크립트와 함께 셀프 호스팅하세요).connect-src: well-known 파일의 매니페스트 가져오기는 동일 오리진이므로 추가 설정이 필요 없습니다. 매니페스트를 키로 로드한다면https://cdn.aidisclose.io를 허용하세요.
매니페스트는 자격 증명 없이 가져오므로 공개적으로 제공하세요: 쿠키나 인증이 필요한 엔드포인트는 그것을 받지 못합니다.
버전 관리와 무결성
CDN은 세 가지 트랙을 제공합니다:
/v1/aidisclose.js는 최신 1.x 릴리스를 따릅니다. 대부분의 사이트에 권장됩니다./v1.0.0/aidisclose.js는 Subresource Integrity와 함께 고정해 둘 수 있는 불변의 고정 버전입니다:
<script src="https://cdn.aidisclose.io/v1.0.0/aidisclose.js"
integrity="sha384-…" crossorigin="anonymous" defer></script>
/latest/aidisclose.js는 메이저 버전에 관계없이 항상 최신 릴리스를 따릅니다.
고정할 SRI 해시를 얻으려면 스니펫을 빌드하세요: packages/snippet에서 npm run build를 실행하면 해시가 출력됩니다(소스는 GitHub에 공개되어 있습니다).
자체 공개 UI 구축
내장 UI 대신 자체 공개 UI를 렌더링할 수 있습니다. 단일 차단 스위치는 없습니다: data-banner="false"와 persistentChip: false는 상호작용 배너와 그 칩만 억제하며, 콘텐츠 고지, 요소별 [data-ai-content] 배지, "made by humans" 배지는 여전히 매니페스트와 마크업으로부터 표시됩니다. 완전한 커스텀 UI란 이들에 의존하지 않고 자체적으로 렌더링하는 것을 뜻합니다.
참고
AIDisclose 검사기는 레퍼런스 스니펫의 마크업을 감지하여 렌더링을 검증합니다. 완전히 손으로 구축한 공개도 유효하지만 자동으로 감지되지는 않으므로, 커스텀 마크업이 검사기가 찾는 것을 재현하지 않는 한 사이트는 Level 2(Rendered)가 아닌 Level 1(Declared)에 머무릅니다. Level 2가 중요하다면 내장 렌더링을 유지하고 CSS로 다시 스타일링하세요.
접근성
렌더링된 UI는 WCAG 2.1 AA를 충족합니다: 상호작용 컨트롤의 가시적인 :focus-visible 윤곽선, 올바른 역할과 라벨, 라이트와 다크에서 유지되는 대비, 그리고 prefers-reduced-motion으로 제어되는 애니메이션. 스니펫은 또한 알려진 쿠키 동의 바를 감지하고 그 위에 쌓여 공개가 CMP 뒤에 가려지지 않도록 합니다. 매우 좁은 화면에서는 상호작용 배너가 콤팩트한 칩으로 열려 콘텐츠를 가리지 않습니다.