Pashto: 47.6M speakers were told Zume had nothing, while its Pashto site was live

Last change joined Zume by exact ISO 639-3 and left pus unjoined, which turned into a
false statement on the map: 13 people groups covering 47.6M speakers read
"Discipleship training - not in Zume's 54" while https://zume.training/pus was live
and in Pashto the whole time. Absence of a variety label is not absence of a resource.

Research for something that selects a variety found nothing that does. The publisher's
launch article scopes Pashto as Afghanistan's other official language and a major
language of northwestern Pakistan, especially Khyber Pakhtunkhwa and parts of
Balochistan - territory spanning all three of pbu, pbt and pst rather than selecting
one. The locale pages declare no language metadata at all: no hreflang alternates, no
BCP-47 tag, and og:locale is the site-wide en_US on every locale including this one.

So it ships as an APPROXIMATE match rather than an exact join or a silence: its own
field, its own dashed chip that reads "Zume, in Pashto (variety not stated)", its own
scope text in the table, never counted as an exact join and unable to move a tier. The
gap filter still cuts 12,379 features to 3,457. It is a curated three-code list, not a
runtime name match - an approximate join a reader cannot see and a gate cannot check is
the one that eventually ships a wrong link.

Why this is defensible here and would not be for film: Zume in Pashto is a written
course in one literary standard, where the pbu/pbt/pst split is largely spoken variety.
The JESUS Film is already in this index under separate per-variety dubs
(pashto-yusufzai, pashto-southern) because a dub differs by pronunciation. The medium
decides.

New gate clause J fails if any code carries both a confirmed and an approximate
training link, or if an approximate entry lacks a url, language or note - that is the
corruption that would make the qualified claim render as the confirmed one. Poison
self-test now 10/10. Both gates also harvest the new field, so its URLs are screened
rather than invisible; the browser gate screens 3,605.

Verified in a browser with three controls: deu renders gm-chip ok with a real href, kri
renders gm-chip meh with no href, pbu renders gm-chip approx linking
https://zume.training/pus and carrying "variety not stated". Screenshot read: the
dashed chip is visibly distinct from both.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 09:37:56 +00:00
parent 2ed595c0f8
commit e04509a94d
24 changed files with 218 additions and 40 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@
"locales": 62,
"live": 54,
"codes": 52,
"approxCodes": 3,
"byIso": {
"amh": {
"locale": "am",
@ -266,6 +267,26 @@
"url": "https://zume.training/zhhk"
}
},
"approx": {
"pbu": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pbt": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pst": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
}
},
"entries": [
{
"locale": "am",

View file

@ -85,6 +85,7 @@ if (POISON) {
...trows.slice(1, -1),
{ ...trows[trows.length - 1], resource_url: 'https://example.invalid/invented' }] // E
rows = [[...rows[0].slice(0, 6), 2], ...rows.slice(1)] // F (forced tier 2)
codes.zzj = { l: 'Both at once', z: 'https://zume.training/en', za: { u: 'https://zume.training/pus', l: 'Pashto', n: 'x' } } // J
}
const SPECIAL = (c) => c === 'und' || c === 'mul' || c === 'mis' || c === 'zxx' || (c >= 'qaa' && c <= 'qtz')
@ -116,7 +117,7 @@ if (missing.length) add('D', `${missing.length} code(s) carry a resource but app
// E — the table cannot invent a URL
const known = new Set()
for (const v of Object.values(codes)) {
if (v.s) known.add(v.s); if (v.f) known.add(v.f); if (v.z) known.add(v.z)
if (v.s) known.add(v.s); if (v.f) known.add(v.f); if (v.z) known.add(v.z); if (v.za) known.add(v.za.u)
for (const d of v.d || []) known.add(d.u)
}
const invented = trows.filter((t) => t.resource_url && !known.has(t.resource_url))
@ -147,7 +148,7 @@ if (misTyped.length) add('H', `${misTyped.length} row(s) named "Open Bible Stori
// G — no plain-http URL
const httpUrls = []
for (const [c, v] of Object.entries(codes)) {
for (const u of [v.s, v.f, v.z, ...(v.d || []).map((d) => d.u)]) {
for (const u of [v.s, v.f, v.z, v.za && v.za.u, ...(v.d || []).map((d) => d.u)]) {
if (u && /^http:\/\//i.test(u)) httpUrls.push(`${c} ${u}`)
}
}
@ -162,13 +163,23 @@ for (const r of rows) {
}
if (fBad) add('F', `${fBad} pin(s) carry a tier that disagrees with their code's URLs`)
// J — an approximate match must never sit alongside a confirmed one on the same code.
// The map styles them differently and says different things, so a code holding both would
// render the qualified claim and the confirmed one as if they were the same resource, and
// the qualification is the entire point of keeping them apart.
const both = Object.entries(codes).filter(([, v]) => v.z && v.za).map(([c]) => c)
if (both.length) add('J', `${both.length} code(s) carry BOTH a confirmed and an approximate training link (e.g. ${both[0]})`)
// An approximate entry must still be a real, complete record rather than a bare URL.
const thin = Object.entries(codes).filter(([, v]) => v.za && !(v.za.u && v.za.l && v.za.n)).map(([c]) => c)
if (thin.length) add('J', `${thin.length} approximate entr(ies) missing a url, language or note (e.g. ${thin[0]})`)
const clauses = new Set(fails.map((f) => f.slice(3, 4)))
if (POISON) {
// D is included deliberately: it is the clause that would have caught the 506
// resources dropped from a table titled "every link", and the most valuable clause is
// the worst one to leave unproven. The injected codes above (und, zzq) are absent from
// the table, so they poison D as well as A and B.
const want = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
const want = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
const caught = want.filter((c) => clauses.has(c))
console.log(`COVERAGE-CONSISTENT --poison: ${caught.length}/${want.length} clause(s) caught their injected defect (${caught.join(',')})`)
if (caught.length !== want.length) {
@ -191,4 +202,4 @@ console.log(' A no resource on an ISO reserved code B every resourced code is
console.log(' C reach recounted off the pins D every resourced code is in the table')
console.log(' E no table URL the pins do not hold F pin tiers match their code\'s URLs')
console.log(' G no plain-http URL H no story set typed as Scripture')
console.log(' I row type agrees with its host')
console.log(' I row type agrees with its host J approximate never reads as confirmed')

View file

@ -141,7 +141,7 @@ try {
const bad = []
let scanned = 0
for (const [c, v] of Object.entries(idx.codes || {})) {
for (const u of [v.s, v.f, v.z, ...(v.d || []).map((d) => d.u)]) {
for (const u of [v.s, v.f, v.z, v.za && v.za.u, ...(v.d || []).map((d) => d.u)]) {
if (!u) continue
scanned++
if (!ALLOWED.test(u)) bad.push(`${c} -> ${u}`)

View file

@ -74,10 +74,32 @@ takes the union and then **fetches every landing URL**, so a locale ships a link
own page actually answered — naming and linking are kept as separate facts rather than one
assumed from the other.
**Pashto is deliberately not joined to any people group.** `pus` is a macrolanguage and the
people-group data carries three individual codes (`pbu`, `pbt`, `pst`); nothing the publisher
gives selects one, so per the standing rule the locale ships with its verified URL and no ISO
code. Guessing would have attached a link to groups that may not read it.
**Pashto is not joined EXACTLY, and is shipped as an approximate match.** `pus` is a
macrolanguage and the people-group data carries three individual codes (`pbu`, `pbt`, `pst`).
What was checked for something that selects one:
- the publisher's launch article scopes Pashto as "Afghanistan's other official language and
a major language of northwestern Pakistan, especially Khyber Pakhtunkhwa and parts of
Balochistan" — territory spanning all three codes, not one;
- the locale pages declare no language metadata at all: no `hreflang` alternates, no BCP-47
tag, and `og:locale` is the site-wide `en_US` on every locale including this one.
So nothing promotes it to an exact join. But leaving it out entirely was itself wrong: it
made 13 people groups covering 47.6M speakers read "not in Zume's 54" while
`https://zume.training/pus` was live and in Pashto. Absence of a variety label is not
absence of a resource.
It therefore ships as an **approximate** match — its own field, its own dashed chip, its own
scope text ("Course in Pashto — variety not stated"), never counted as an exact join and
never able to move a tier. Clause J of the coverage gate fails if a code ever carries both a
confirmed and an approximate training link, because that is the corruption that would make
the qualified claim render as the confirmed one.
The reason this is defensible for Zume and would NOT be for the JESUS Film: Zume in Pashto is
a written course in one literary standard, where the pbu/pbt/pst split is largely spoken
variety. The JESUS Film is already in this index under separate per-variety dubs
(`pashto-yusufzai`, `pashto-southern`) because a dub genuinely differs by pronunciation. The
medium decides.
**Zume moves no tier and shrinks no gap.** It is discipleship training, not Scripture and not
film, so it is carried in its own field and typed "Discipleship training". Measured: its 52

View file

@ -382,6 +382,7 @@ function groupAt(i) {
unchecked_pools: c.un || '',
is_sign: c.sg === 1,
zume_url: c.z || '',
zume_approx: c.za || null,
scripture_title: c.sv || '',
scripture_scope: c.ss || '',
code_note: r[4] ? '' : 'This group has no ISO 639-3 code in the source, so no resource lookup is possible for it.',
@ -776,6 +777,10 @@ useShadowStyles(
'.gm-chip.bad{background:rgba(180,35,24,.16);border-color:rgba(180,35,24,.38)}' +
'.gm-chip.warn{background:rgba(224,122,43,.18);border-color:rgba(224,122,43,.38)}' +
'.gm-chip.meh{background:rgba(120,130,140,.16);border-color:rgba(120,130,140,.30)}' +
// APPROXIMATE: the same green family as a confirmed chip, because the resource is real,
// but DASHED and unfilled so it never reads as the same claim at a glance.
'.gm-chip.approx{background:transparent;border-style:dashed;border-color:rgba(16,185,129,.55)}' +
'.gm-chip.approx em{font-style:normal;opacity:.7}' +
// Only an ANCHOR chip gets the pointer + underline. A <span> chip ("none found",
// "unknown") must keep looking inert, because it is.
'a.gm-chip{cursor:pointer}' +
@ -984,6 +989,16 @@ useShadowStyles(
title="Zume Training publishes its discipleship course in this language — free, no account needed to read it.">
Discipleship training · Zume
</a>
<!-- APPROXIMATE, and it says so on its face. Zume publishes a written course
in this language but does not state which variety, and this group speaks
one of several. Saying "not in Zume's 54" here was false for 13 groups
covering 47.6M speakers; saying "Zume" flat would have been an overclaim.
The chip is styled apart from a confirmed one so the two never read alike. -->
<a v-else-if="selectedGroup.zume_approx" class="gm-chip approx"
:href="selectedGroup.zume_approx.u" target="_blank" rel="noopener noreferrer"
:title="selectedGroup.zume_approx.n + '. The course is written in one standard script, so it is likely to be readable — but it was not published against this ISO code and is shown as an approximate match, not a confirmed one.'">
Discipleship training · Zume, in {{ selectedGroup.zume_approx.l }} <em>(variety not stated)</em>
</a>
<span v-else class="gm-chip meh"
title="Zume Training publishes in 54 languages and this is not one of them. That is a gap in one training platform, not a statement about every training resource.">
Discipleship training · not in Zume's 54

View file

@ -122,7 +122,15 @@ const filmUrl = (code, aa) => httpsify(share[code] || (aa ? aa.u : ''))
// "Scripture and/or film", and quietly folding a third kind of resource into them would
// shrink the gap count without anyone having translated anything.
let zume = {}
try { zume = JSON.parse(readFileSync(ZUME, 'utf8')).byIso || {} } catch { zume = {} }
let zumeApprox = {}
try {
const j = JSON.parse(readFileSync(ZUME, 'utf8'))
zume = j.byIso || {}
// Approximate matches ride in a SEPARATE field so no count, tier or gate can mistake
// one for an exact join. They exist because "we publish in your language but cannot
// say which variety" is a real answer and "nothing found" is not.
zumeApprox = j.approx || {}
} catch { zume = {}; zumeApprox = {} }
// codes: one entry per ISO 639-3 that actually carries something worth linking to.
const codes = {}
@ -296,6 +304,15 @@ for (const [c, z] of Object.entries(zume)) {
codes[c].z = httpsify(z.url)
zumeCodes++
}
let zumeApproxCodes = 0
for (const [c, a] of Object.entries(zumeApprox)) {
// Never overwrite an exact join with an approximate one, and never create a code that
// does not already exist: an approximate match is extra information about a language
// already on this map, not grounds for inventing a new one.
if (!codes[c] || codes[c].z) continue
codes[c].za = { u: httpsify(a.url), l: a.lang, n: a.note }
zumeApproxCodes++
}
const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : null }
const pins = []
@ -353,6 +370,7 @@ console.log(`ebible codes ${Object.keys(eb).length} (${ebOnly} new)`)
console.log(`arclight codes ${Object.keys(arc).length} (${arcOnly} new, ${upgraded} upgraded to a real deep link)`)
console.log(`share urls ${Object.keys(share).length}`)
console.log(`zume languages ${zumeCodes} (${zumeNew} new codes; training only, tier unchanged)`)
console.log(`zume approximate ${zumeApproxCodes} (published in the language, variety not stated; never counted as an exact join)`)
console.log(`named from cat ${catNamed} (no pin speaks them; named from a catalogue)`)
console.log(`sign languages ${signCodes}`)
console.log(`named-only ${namedOnly} (language named, no resource in any pool checked)`)

View file

@ -99,6 +99,10 @@ for (const [code, c] of Object.entries(codes)) {
// Its own type. Zume is a discipleship COURSE, not a translation and not a film, and
// filing it under Scripture would overstate what a reader gets by following the link.
add('Zume Training', 'Discipleship training', c.z, 'Course in this language')
// The approximate match ships too, with the qualification IN THE SCOPE COLUMN. Leaving
// it out would make the table disagree with the map for these languages, and a reader
// who filters the table to Pashto would be told there is no training when there is.
if (c.za) add('Zume Training', 'Discipleship training', c.za.u, `Course in ${c.za.l} — variety not stated`)
}
// biggest reach first — the link that serves the most people is the one to open.
out.sort((a, b) => b.speakers - a.speakers || a.language.localeCompare(b.language))

View file

@ -116,6 +116,38 @@ const UNJOINED = {
pus: 'Pashto has three individual codes in the people-group data (pbu, pbt, pst) and the publisher gives nothing that selects one',
}
/**
* APPROXIMATE matches, kept STRICTLY apart from the exact joins above.
*
* An unjoined locale is not the same as an absent resource, and conflating the two is how
* 13 people groups covering 47.6M speakers came to be told "not in Zume's 54" while
* https://zume.training/pus was live and in Pashto the whole time.
*
* WHAT WAS CHECKED BEFORE WRITING THIS DOWN. The publisher's launch article scopes Pashto
* as "Afghanistan's other official language and a major language of northwestern Pakistan,
* especially Khyber Pakhtunkhwa and parts of Balochistan" — territory that spans all three
* codes rather than selecting one. The pages themselves declare no language metadata at
* all: no hreflang alternates, no BCP-47 tag, and og:locale is the site-wide en_US on every
* locale including this one. So nothing promotes this to an exact join.
*
* WHY IT IS STILL WORTH SHIPPING. Zume in Pashto is a WRITTEN course in Pashto script, and
* written Pashto is one literary standard; the pbu/pbt/pst split is largely spoken variety.
* Contrast the JESUS Film, which is already in this index under separate per-variety dubs
* (pashto-yusufzai, pashto-southern) because a dub genuinely differs by pronunciation. The
* medium decides, so this is recorded as approximate and labelled as such everywhere it is
* shown, never folded into the exact counts and never used to move a tier.
*
* This is a curated list, not a fuzzy name match at runtime — an approximate join that a
* reader cannot see and a gate cannot check is the one that eventually ships a wrong link.
*/
const APPROX = {
pus: {
iso: ['pbu', 'pbt', 'pst'],
lang: 'Pashto',
note: 'Published in Pashto; the publisher does not say which variety, and this group speaks one of three',
},
}
const get = async (url) => {
const r = await fetch(url, { headers: { 'user-agent': UA }, redirect: 'follow' })
if (!r.ok) throw new Error(`${r.status} ${url}`)
@ -193,6 +225,14 @@ for (const e of entries) {
if (!prev) byIso[e.iso] = { locale: e.locale, name: e.name || e.locale, url: e.url }
}
// Approximate joins, resolved against what actually came back live.
const approx = {}
for (const [locale, a] of Object.entries(APPROX)) {
const e = entries.find((x) => x.locale === locale)
if (!e || !e.url) continue
for (const iso of a.iso) approx[iso] = { locale, lang: a.lang, note: a.note, url: e.url }
}
const unjoined = entries.filter((e) => !e.iso).map((e) => e.locale)
const dead = entries.filter((e) => !e.url).map((e) => e.locale)
@ -205,7 +245,9 @@ writeFileSync(
locales: entries.length,
live,
codes: Object.keys(byIso).length,
approxCodes: Object.keys(approx).length,
byIso,
approx,
entries,
},
null,
@ -218,4 +260,7 @@ console.log(
`${live} with a landing page that answers 200, ${Object.keys(byIso).length} joined to ISO 639-3.`,
)
if (unjoined.length) console.log(`ZUME: not joined -> ${unjoined.join(', ')}`)
if (Object.keys(approx).length) {
console.log(`ZUME: approximate -> ${Object.entries(approx).map(([i, a]) => `${i} (${a.locale})`).join(', ')}`)
}
if (dead.length) console.log(`ZUME: no live page -> ${dead.join(', ')}`)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@
"locales": 62,
"live": 54,
"codes": 52,
"approxCodes": 3,
"byIso": {
"amh": {
"locale": "am",
@ -266,6 +267,26 @@
"url": "https://zume.training/zhhk"
}
},
"approx": {
"pbu": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pbt": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pst": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
}
},
"entries": [
{
"locale": "am",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@
"locales": 62,
"live": 54,
"codes": 52,
"approxCodes": 3,
"byIso": {
"amh": {
"locale": "am",
@ -266,6 +267,26 @@
"url": "https://zume.training/zhhk"
}
},
"approx": {
"pbu": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pbt": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
},
"pst": {
"locale": "pus",
"lang": "Pashto",
"note": "Published in Pashto; the publisher does not say which variety, and this group speaks one of three",
"url": "https://zume.training/pus"
}
},
"entries": [
{
"locale": "am",

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
<script src="../gospel-resources.js" integrity="sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv" crossorigin="anonymous"></script>
<script src="../gospel-resources.js" integrity="sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -556,7 +556,7 @@
"bundle": "gospel-resources",
"scriptUrl": "./gospel-resources/gospel-resources.js",
"output": "doxa-maps/gospel-resources/gospel-resources.js",
"integrity": "sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv",
"integrity": "sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb",
"elements": [
"gospel-resources-map"
],
@ -576,7 +576,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -590,7 +590,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -604,7 +604,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -618,7 +618,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
},
{
@ -632,7 +632,7 @@
"scriptUrl": "./gospel-resources/gospel-resources.js",
"embed": {
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-uwrH85RSM2vEAotqNQInLLXZl7ZYKd/Ah/DyxDA3Em61va9qbQHFtcKUwMy+P+gv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-P1fIhucAOViVufa8/Hsc3BgNWzZVSXlY/Pv/HYeV+RsKXol8mmPmPExXGmArpuIb\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
}
}
]