変換スクリプト:取り込みの途中に割り込む仕組み
インポート・連携シリーズの6本目です。前回まで、データソース・変換マップ・coalesce・スケジュールと、取り込みの骨格を見てきました。今回は、その変換処理の途中に割り込む仕組み、変換スクリプト(sys_transform_script)を扱います。
②の変換マップの回で、マップ本体にも Script 欄があると触れました。それとは別に、「変換のこのタイミングで動く」というイベント単位のスクリプトが用意されています。取り込みの前後や、各行の変換前後に、独自の処理を挟める。実機の12件を教材に、その仕組みを読み解きます。
取り込みと連携の全体像は ServiceNowのデータ連携 全体地図 にまとめました。
この記事は、ServiceNow の PDI(Personal Developer Instance、無料の個人検証環境)Zurich リリース・OOTB(初期設定)で確認した実測メモです。件数・スクリプト内容はすべて REST と実画面で確認しました(確認日 2026-07-13)。本番環境では設定が異なります。
変換スクリプトとは:タイミングで割り込む
変換スクリプトは、変換処理の決まったタイミングで自動的に走るスクリプトです。「取り込みが始まったとき」「各行を変換する直前」「変換が全部終わったとき」など、いつ走らせるかを指定できます。
マップ本体の Script が「1つの項目の値を作る」ためのものだったのに対し、変換スクリプトは「変換の流れに割り込んで、独自の処理を差し込む」ためのものです。たとえば、条件に合わない行をスキップする、変換後に別のテーブルを更新する、といった処理を書けます。取り込みの本流はそのままに、要所に自分の処理を挟む。それが変換スクリプトの役割です。
イメージとしては、工場の生産ラインに立つ検査員に近いです。ラインの流れ(変換)はそのまま動いていて、その決まった位置に検査員(スクリプト)を配置する。検査員は、流れてきた品物を点検し、不良品を弾いたり、印を付けたりします。どの位置に立たせるか(when)で、検査員の役割が変わる。開始点に立たせれば準備係、各品物の前に立たせれば門番、終点に立たせれば集計係です。変換スクリプトは、この「ラインのどこに、どんな検査員を立てるか」を決める仕組みだと捉えると、全体像がつかみやすくなります。
when:割り込む5つのタイミング
いつ割り込むかは、when というフィールドで決めます。実機で確認できたタイミングは、次の5種類でした。

onStart … 変換の開始時(全体で1回だけ)
onBefore … 各行を変換する直前(行ごとに走る)
onAfter … 各行を変換した直後(行ごとに走る)
onComplete … 変換の完了時(全体で1回だけ)
onReject … 行が拒否されたとき
onStart と onComplete は「取り込み全体で1回」、onBefore と onAfter は「行ごとに1回ずつ」走ります。だから、全体の前処理・後処理は onStart / onComplete、1行ごとの細かい判断は onBefore / onAfter、と使い分けます。

図にすると、取り込みの流れの「どこ」で各タイミングが発火するかが見えます。開始で onStart、各行のループの中で onBefore →(変換)→ onAfter、全部終わって onComplete。onBefore で ignore を立てれば、その行は変換されずに飛ばされます。5つのタイミングは、この一本の流れの上に並んでいるだけです。
実測の分布も見ておきます。

12件を when で分類すると、onBefore が8件で圧倒的多数でした。ほかは onStart 2件、onAfter 1件、onComplete 1件、onReject 0件です。1行ごとに判断を挟む onBefore が主役です。取り込みで独自処理を書きたい場面の多くは、「この行を入れるか、どう変えるか」という行単位の判断です。この分布から、それが読み取れます。
onBefore を開く:行をスキップする
いちばん多い onBefore の実例を見ます。OIDC 連携の検証スクリプトです。

When は onBefore、Active はオン。中身のコードはこうなっていました。
(function runTransformScript(source, map, log, target) {
var oidcTransformCheck = new OIDCTransformCheck(source, map, log, target);
var isMappingValid = oidcTransformCheck.validateMappingOnBefore();
if(!isMappingValid) {
ignore = true;
}
})(source, map, log, target);読むと素直です。OIDC のマッピングが正しいかを検証し、正しくなければ ignore = true を立てています。この ignore = true が肝で、これを立てると、その行の取り込みがスキップされます。つまり「不正なデータの行は、本番に入れずに飛ばす」という門番の役割です。onBefore で行の中身を点検し、条件に合わない行をここで弾く。これが onBefore の典型的な使い方です。
画面には「このスクリプトの機能と、使えるグローバルは、いつ実行するか(when)で変わる」という注意書きも出ていました。同じ書き方でも、when によって使える道具が変わる、という点は覚えておきたいところです。
onBefore が門番として優秀なのは、「本番に入る前」に判断できるからです。もし onAfter(変換後)でおかしなデータに気づいても、そのときには既に本番レコードができています。取り消すには余計な手間がかかります。onBefore なら、問題のある行を「入れる前」に弾けるので、本番が汚れません。だから、取り込むデータの品質を守りたいなら、まず onBefore で点検する、というのが定石になります。OIDC の検証スクリプトが onBefore に置かれているのも、この「入れる前に止める」ためでした。データの入口に門番を立てる、という発想です。
4つの引数:source・target・map・log
コードの1行目に runTransformScript(source, map, log, target) とあります。この4つが、変換スクリプトで使える道具です。
source … ステージング行(取り込んだ生データ)。source.email のように読む
target … 作ろうとしている本番レコード。target.user_name = ... のように書く
map … 適用中の変換マップ
log … ログ出力用のオブジェクト
②で見たマップ本体の Script も、同じ source と target を使っていました。ステージングの値を読み、本番レコードに書く。この2つの変数を軸に、変換の途中で値を触れます。ただし注意点があり、onStart のときは source と target がまだ存在しません(コードのコメントにも「undefined onStart」とありました)。onStart は「行の処理が始まる前」なので、まだどの行も扱っていないからです。when によって使える道具が変わる、というのは、こういうことです。
具体的に言うと、onStart で source.email を読もうとしても、source が無いのでエラーになります。onStart では、まだ行に触れず、全体の準備だけをする。一方、onBefore や onAfter なら、source も target も揃っているので、行の値を自由に読み書きできます。だから「行のデータを使う処理」は onBefore / onAfter に、「行に関係ない全体の準備・締め」は onStart / onComplete に書く、という住み分けになります。使える道具が when で変わるからこそ、書く処理の内容に合わせて when を選ぶ、という順番で考えると間違えません。画面の注意書きが「使えるグローバルは when で変わる」と念を押しているのは、この落とし穴を避けさせるためでした。
onAfter・onComplete・onReject の使いどころ
残りのタイミングも押さえます。onAfter は、各行の変換が終わった直後です。target(本番レコード)ができあがっているので、「作ったレコードを使って、さらに別の処理をする」のに向きます。たとえば、作ったユーザーに紐づく別のレコードを作る、といった後処理です。

実機の onAfter スクリプトも、同じ runTransformScript(source, map, log, target) の形をしていました。違うのは When が onAfter になっている点だけです。書き方の枠は共通で、いつ走るか(when)を変えるだけで、割り込むタイミングが変わる。この統一された作りのおかげで、1つの書き方を覚えれば、どのタイミングのスクリプトも同じ要領で書けます。
onComplete は、変換が全部終わったあとに1回だけ走ります。「今回の取り込みで何件処理したか集計する」「担当者に完了を通知する」といった、締めの処理に向いています。onReject は、行が拒否されたときに発火する枠です。今回の環境では0件でしたが、「なぜ弾かれたかを記録する」といったエラー処理の窓口になります。
onStart で準備し、onBefore で門番、onAfter で後処理をします。onComplete で締め、onReject でエラー対応をします。この5つのタイミングを、取り込みの流れに沿って並べると、どこに何を書けばよいかが見えてきます。
マップ本体の Script との違い
ここでは、②で見たマップ本体の Script と、この変換スクリプトの違いを比べます。
マップ本体の Script は、フィールドの値を作るためのものでした。User マップなら、氏名から user_name を組み立てる、といった値の生成に使います。一方、この変換スクリプトは、変換の流れに割り込むためのものです。行をスキップする、後処理を挟む、といった処理の制御を担います。
同じ「スクリプト」でも、片方は値を作り、もう片方は処理に割り込む。書く場所も違います。値の生成はマップの Script 欄、割り込みは sys_transform_script という別レコードです。どちらを使うべきかは、「値を作りたいのか、処理を挟みたいのか」で決まります。この使い分けを間違えると、意図したタイミングで動かず悩むことになるので、最初に押さえておきたい区別です。

sys_transform_script のテーブル定義を見ると、いくつかの列が並んでいます。when や script、map、order、active などです。ここで意外なのは、name(名前)の列が無いことです。変換スクリプトは「どのマップの、どの when か」で識別され、名前を持ちません。だから一覧では、名前ではなく map と when で見分けます。この点は、名前で探そうとすると戸惑うので、実測から得た注意点として覚えておくと役立ちます。列の作りが分かると、REST やスクリプトから変換スクリプトを扱うときにも迷いません。同じマップに複数の when スクリプトをぶら下げることもできます。「このマップの onBefore と onAfter」を並べて見たいときは、map で絞ってから when で並べ替える、という探し方が便利です。
書く場所を間違えないために
変換にまつわるスクリプトの居場所を、ここで一度まとめます。②とこの回で見たとおり、変換の中には「スクリプトを書ける場所」が3つあります。
マップ本体の Script(sys_transform_map.script)… フィールドの値をその場で生成
変換スクリプト(sys_transform_script)… 変換の各タイミングに割り込む(今回)
フィールドマップの Source script(sys_transform_entry)… 1項目の値を作る小さなスクリプト
同じ「変換のスクリプト」でも、この3つは動くタイミングも範囲も違います。1項目だけの加工ならフィールドマップの Source script、行全体やマップ全体に関わる値の生成ならマップ本体の Script、処理の流れに割り込むなら変換スクリプト。書きたい処理が「どの粒度」で「いつ」動くべきかを考えれば、3つのどこに書くべきかが決まります。この地図を持っておくと、「書いたのに動かない」「意図しないタイミングで動く」といったつまずきを避けられます。取り込みのスクリプトで悩んだら、まずこの3つのどれの話かを切り分けるのが近道です。
一覧で全体を見る
最後に、変換スクリプトの一覧に戻ります。

12件が when で並んでいます。それぞれ、どの変換マップに紐づくかも分かります。OIDC 系のマップ(Okta / Google / ADFS / Auth0 / Azure)は、いずれも同じ形の onBefore 検証スクリプトを持っていました。外部IdP から取り込むユーザーデータは、マッピングの妥当性を1行ずつ点検してから入れる、という共通の作りになっています。門番を各マップに置く、というパターンが、この一覧からも読み取れます。
同じ処理を5つのマップが持っている、というのは、裏を返せば「外部IdP 連携では、この検証が定番だ」という証拠でもあります。IdP ごとにデータの形は微妙に違いますが、「取り込む前にマッピングを点検し、おかしければ弾く」という守り方は共通です。だから ServiceNow は、各 IdP マップに同じ形の門番を配りました。もし自社で新しい取り込みを作るなら、この OOTB の onBefore スクリプトは、良いお手本になります。ignore = true で行を弾く書き方は、そのまま応用できるからです。実機の標準レコードは、機能の説明であると同時に、自分で書くときの雛形でもあります。こうした一覧を読むと、その両方が分かります。
確認導線
実機で開くときの入口です(URL形式は list.do 規約に基づきます。実クリック確認は今回の範囲外です)。
変換スクリプト一覧 … sys_transform_script_list.do(when 列で並べ替え)
変換スクリプト1件 … sys_transform_script.do?sys_id=...
変換マップの関連リスト「Transform Scripts」
まとめ
変換スクリプトは、取り込みの変換処理に「決まったタイミングで割り込む」仕組みでした。when で onStart / onBefore / onAfter / onComplete / onReject の5つから選びます。source・target・map・log の4つの道具で処理を書きます。実機の12件は onBefore が主役で、ignore = true による行のスキップが典型例でした。
マップ本体の Script が「値を作る」なら、変換スクリプトは「処理に割り込む」。役割と書く場所を分けて覚えておくと、取り込みで独自処理を書きたくなったとき、迷わず正しい場所に手を入れられます。
改めて振り返ると、取り込みの変換は、ただ機械的に列を移すだけの単純な作業ではありませんでした。マップで対応づけ、coalesce で重複を防ぎ、スクリプトで値を作り、そして変換スクリプトで要所に判断を挟む。何段もの仕組みが重なって、外部の雑多なデータを、本番で使える整ったデータに仕立てています。変換スクリプトは、その最後の細かな調整を担う部品です。派手ではありませんが、「この行は入れない」「取り込み後にこれをする」という現場ごとの要望を、ここで吸収します。標準機能だけでは足りない一手間を、決まったタイミングで差し込める。この余地があるからこそ、ServiceNow の取り込みは、多様な現場に適応できるわけです。
次回は、取り込みの結果を記録するログとエラー行を見ていきます。うまくいったか、どこで失敗したかを、どこで確認するかの話です。
その他、実機で確認した記録
用語
変換スクリプト(sys_transform_script) … 変換の特定タイミングに割り込むスクリプト
when … 割り込むタイミング(onStart / onBefore / onAfter / onComplete / onReject)
ignore = true … onBefore で立てると、その行の取り込みをスキップ
source / target … ステージング行 / 作ろうとしている本番レコード
マップ本体の Script との違い … 値の生成(マップ)vs 処理への割り込み(変換スクリプト)
自分の環境で確認するときのURL
自分のインスタンス名を先頭に付けると、同じ画面が開けます。
/sys_transform_script_list.do?sysparm_query=ORDERBYwhen(変換スクリプト12件)
/sys_transform_script.do?sys_id=...(1スクリプトの when とコード)
変換マップの「Transform Scripts」関連リスト
実測の要点(再掲)
sys_transform_script 12件。when 内訳: onBefore 8 / onStart 2 / onAfter 1 / onComplete 1 / onReject 0
シグネチャ: runTransformScript(source, map, log, target)
onBefore の典型: 検証して不正なら ignore = true でスキップ(OIDC 系)
onStart では source / target が undefined(行処理の前だから)
検証範囲とおことわり
この記事の件数・when 内訳・スクリプト内容・シグネチャは、PDI(Zurich / OOTB)の実測です。
実際に変換を実行してスクリプトが発火する様子は、sys_import_set が0件のため未確認(検証範囲外)です。
OIDC 検証スクリプトは標準同梱のレコードで、実機では原則書き換えません。
list.do のURL形式は規約に基づくもので、実クリック確認は今回の範囲外です。