@redonvn/zalo-ads-sdk 0.2.20 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +382 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +380 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
VALID_AD_TYPES: () => VALID_AD_TYPES,
|
|
50
50
|
VALID_CAMPAIGN_TYPES: () => VALID_CAMPAIGN_TYPES,
|
|
51
51
|
VIETNAM_PHONE_REGEX: () => VIETNAM_PHONE_REGEX,
|
|
52
|
+
ZALO_DISPLAY_AD_FORMAT: () => ZALO_DISPLAY_AD_FORMAT,
|
|
52
53
|
ZALO_NEW_REGION_PROVINCE_CODES: () => ZALO_NEW_REGION_PROVINCE_CODES,
|
|
53
54
|
ZALO_PROFILE_ADS_PROVINCES: () => ZALO_PROFILE_ADS_PROVINCES,
|
|
54
55
|
ZALO_PROFILE_ADS_SUB_CATEGORIES: () => ZALO_PROFILE_ADS_SUB_CATEGORIES,
|
|
@@ -84,6 +85,7 @@ __export(index_exports, {
|
|
|
84
85
|
ZaloAdsUpdateVideoAdRequest: () => ZaloAdsUpdateVideoAdRequest,
|
|
85
86
|
ZaloAdsUpdateVideoAdResponse: () => ZaloAdsUpdateVideoAdResponse,
|
|
86
87
|
ZaloAdsUseConversion: () => ZaloAdsUseConversion,
|
|
88
|
+
ZaloAdsVideoPlatform: () => ZaloAdsVideoPlatform,
|
|
87
89
|
ZaloAdsVideoSrc: () => ZaloAdsVideoSrc,
|
|
88
90
|
ZaloAdsXTemplates: () => ZaloAdsXTemplates,
|
|
89
91
|
ZaloAudiencesService: () => ZaloAudiencesService,
|
|
@@ -1960,11 +1962,15 @@ var ZaloAdsActionType = {
|
|
|
1960
1962
|
MUA_NGAY: 2,
|
|
1961
1963
|
THU_NGAY: 3,
|
|
1962
1964
|
TAI_NGAY: 4,
|
|
1965
|
+
/** Nút "Xem thêm" trên Quảng cáo Form (Type 18) gửi mã 4 */
|
|
1966
|
+
XEM_THEM_FORM: 4,
|
|
1963
1967
|
XEM_THEM: 5,
|
|
1964
1968
|
NGHE_NGAY: 6,
|
|
1965
1969
|
CHOI_NGAY: 7,
|
|
1966
1970
|
DANG_KY: 8,
|
|
1967
1971
|
GOI_DIEN: 9,
|
|
1972
|
+
/** Nút bấm "Gửi tin nhắn" / "Nhắn tin" dành cho Quảng cáo Tin nhắn (Type 19/30) */
|
|
1973
|
+
NHAN_TIN: 10,
|
|
1968
1974
|
/** Dành riêng cho Quảng cáo Official Account (Type 2) */
|
|
1969
1975
|
QUAN_TAM_OA: 6
|
|
1970
1976
|
};
|
|
@@ -1975,6 +1981,12 @@ var ZaloAdsVideoSrc = {
|
|
|
1975
1981
|
/** Tự tải video lên hoặc chọn từ Thư viện Media */
|
|
1976
1982
|
SELF_UPLOAD: 2
|
|
1977
1983
|
};
|
|
1984
|
+
var ZaloAdsVideoPlatform = {
|
|
1985
|
+
/** Nền tảng Video (toàn màn hình như ZVideo, Báo Mới; sàn CPM 7,300đ) */
|
|
1986
|
+
VIDEO_NETWORK: 1,
|
|
1987
|
+
/** Nhật ký Zalo (Feed xen giữa tin bạn bè; sàn CPM 6,000đ) */
|
|
1988
|
+
ZALO_FEED: 2
|
|
1989
|
+
};
|
|
1978
1990
|
var ZaloAdsBudgetScheduleType = {
|
|
1979
1991
|
/** Toàn lịch chạy */
|
|
1980
1992
|
TOTAL_SCHEDULE: 1,
|
|
@@ -2228,13 +2240,33 @@ var VALID_CAMPAIGN_TYPES = {
|
|
|
2228
2240
|
var VALID_AD_TYPES = {
|
|
2229
2241
|
WEBSITE: 5,
|
|
2230
2242
|
FORM: 18,
|
|
2231
|
-
MESSAGE:
|
|
2243
|
+
MESSAGE: 19,
|
|
2244
|
+
// Mã chuẩn của máy chủ Zalo Ads khi UpdateAd
|
|
2245
|
+
MESSAGE_LEGACY: 30,
|
|
2246
|
+
// Hỗ trợ tương thích ngược
|
|
2232
2247
|
OA: 2,
|
|
2233
2248
|
VIDEO: 11,
|
|
2234
2249
|
COMMERCE: 28,
|
|
2235
2250
|
// Server trả về 28 (không phải 23)
|
|
2236
2251
|
ARTICLE: 3,
|
|
2237
|
-
DISPLAY: 21
|
|
2252
|
+
DISPLAY: 21,
|
|
2253
|
+
// Masthead Mobile (Format 1) & Masthead Desktop (Format 2)
|
|
2254
|
+
DISPLAY_HALFPAGE: 26,
|
|
2255
|
+
// Halfpage Mobile (Format 13) & Halfpage PC (Format 14)
|
|
2256
|
+
DISPLAY_MEDIUM_RECTANGLE: 23
|
|
2257
|
+
// Medium Rectangle 300x250 (Format 6)
|
|
2258
|
+
};
|
|
2259
|
+
var ZALO_DISPLAY_AD_FORMAT = {
|
|
2260
|
+
MASTHEAD_MOBILE: 1,
|
|
2261
|
+
// Kích thước 640x360, Os: [0, 1]
|
|
2262
|
+
MASTHEAD_DESKTOP: 2,
|
|
2263
|
+
// Kích thước 970x250, Os: [3]
|
|
2264
|
+
MEDIUM_RECTANGLE: 6,
|
|
2265
|
+
// Kích thước 300x250, Os: [0, 1]
|
|
2266
|
+
HALFPAGE_MOBILE: 13,
|
|
2267
|
+
// Kích thước 300x600, Os: [0, 1]
|
|
2268
|
+
HALFPAGE_PC: 14
|
|
2269
|
+
// Kích thước 300x600, Os: [3]
|
|
2238
2270
|
};
|
|
2239
2271
|
var ALLOWED_CTAS_PER_AD_TYPE = {
|
|
2240
2272
|
// Website (Type 5): 9 CTAs
|
|
@@ -2270,22 +2302,71 @@ var ALLOWED_CTAS_PER_AD_TYPE = {
|
|
|
2270
2302
|
ZaloAdsActionType.CHOI_NGAY,
|
|
2271
2303
|
ZaloAdsActionType.DANG_KY
|
|
2272
2304
|
],
|
|
2273
|
-
// Form (Type 18): 5 CTAs
|
|
2305
|
+
// Form (Type 18): 5 CTAs (Đặt ngay: 1, Mua ngay: 2, Thử ngay: 3, Xem thêm: 4/5, Đăng ký: 8)
|
|
2274
2306
|
[VALID_AD_TYPES.FORM]: [
|
|
2275
2307
|
ZaloAdsActionType.DAT_NGAY,
|
|
2276
2308
|
ZaloAdsActionType.MUA_NGAY,
|
|
2277
2309
|
ZaloAdsActionType.THU_NGAY,
|
|
2310
|
+
4,
|
|
2278
2311
|
ZaloAdsActionType.XEM_THEM,
|
|
2279
2312
|
ZaloAdsActionType.DANG_KY
|
|
2280
2313
|
],
|
|
2281
|
-
// Commerce (Type 28): 3 CTAs
|
|
2314
|
+
// Commerce (Type 28): 3 CTAs (Đặt ngay: 1, Mua ngay: 2, Xem thêm: 4/5)
|
|
2282
2315
|
[VALID_AD_TYPES.COMMERCE]: [
|
|
2283
2316
|
ZaloAdsActionType.DAT_NGAY,
|
|
2284
2317
|
ZaloAdsActionType.MUA_NGAY,
|
|
2318
|
+
4,
|
|
2285
2319
|
ZaloAdsActionType.XEM_THEM
|
|
2286
2320
|
],
|
|
2287
2321
|
// OA (Type 2): Cố định Quan tâm OA (6)
|
|
2288
|
-
[VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA]
|
|
2322
|
+
[VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA],
|
|
2323
|
+
// Message (Type 19 & Type 30 legacy):
|
|
2324
|
+
[VALID_AD_TYPES.MESSAGE]: [
|
|
2325
|
+
ZaloAdsActionType.NHAN_TIN,
|
|
2326
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2327
|
+
ZaloAdsActionType.DANG_KY,
|
|
2328
|
+
ZaloAdsActionType.GOI_DIEN
|
|
2329
|
+
],
|
|
2330
|
+
[VALID_AD_TYPES.MESSAGE_LEGACY]: [
|
|
2331
|
+
ZaloAdsActionType.NHAN_TIN,
|
|
2332
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2333
|
+
ZaloAdsActionType.DANG_KY,
|
|
2334
|
+
ZaloAdsActionType.GOI_DIEN
|
|
2335
|
+
],
|
|
2336
|
+
// Display (Type 21) & Display Halfpage (Type 26): Hỗ trợ các hành động cơ bản
|
|
2337
|
+
[VALID_AD_TYPES.DISPLAY]: [
|
|
2338
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2339
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2340
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2341
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2342
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2343
|
+
ZaloAdsActionType.NGHE_NGAY,
|
|
2344
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2345
|
+
ZaloAdsActionType.DANG_KY,
|
|
2346
|
+
ZaloAdsActionType.GOI_DIEN
|
|
2347
|
+
],
|
|
2348
|
+
[VALID_AD_TYPES.DISPLAY_HALFPAGE]: [
|
|
2349
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2350
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2351
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2352
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2353
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2354
|
+
ZaloAdsActionType.NGHE_NGAY,
|
|
2355
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2356
|
+
ZaloAdsActionType.DANG_KY,
|
|
2357
|
+
ZaloAdsActionType.GOI_DIEN
|
|
2358
|
+
],
|
|
2359
|
+
[VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE]: [
|
|
2360
|
+
ZaloAdsActionType.DAT_NGAY,
|
|
2361
|
+
ZaloAdsActionType.MUA_NGAY,
|
|
2362
|
+
ZaloAdsActionType.THU_NGAY,
|
|
2363
|
+
ZaloAdsActionType.TAI_NGAY,
|
|
2364
|
+
ZaloAdsActionType.XEM_THEM,
|
|
2365
|
+
ZaloAdsActionType.NGHE_NGAY,
|
|
2366
|
+
ZaloAdsActionType.CHOI_NGAY,
|
|
2367
|
+
ZaloAdsActionType.DANG_KY,
|
|
2368
|
+
ZaloAdsActionType.GOI_DIEN
|
|
2369
|
+
]
|
|
2289
2370
|
};
|
|
2290
2371
|
function validateCreateCampaignPayload(payload, options = {}) {
|
|
2291
2372
|
const errors = [];
|
|
@@ -2321,8 +2402,9 @@ function validateCreateCampaignPayload(payload, options = {}) {
|
|
|
2321
2402
|
}
|
|
2322
2403
|
switch (payload.campaignType) {
|
|
2323
2404
|
case VALID_CAMPAIGN_TYPES.WEBSITE:
|
|
2405
|
+
case VALID_CAMPAIGN_TYPES.VIDEO:
|
|
2324
2406
|
if (!payload.targetUrl || typeof payload.targetUrl !== "string" || !payload.targetUrl.trim()) {
|
|
2325
|
-
errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website.");
|
|
2407
|
+
errors.push("targetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Website / Video.");
|
|
2326
2408
|
} else if (!/^https?:\/\/.+/i.test(payload.targetUrl)) {
|
|
2327
2409
|
errors.push("targetUrl ph\u1EA3i l\xE0 m\u1ED9t \u0111\u01B0\u1EDDng link h\u1EE3p l\u1EC7 b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https://.");
|
|
2328
2410
|
}
|
|
@@ -2381,11 +2463,15 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2381
2463
|
if (!adInfo) {
|
|
2382
2464
|
errors.push("Settings.AdInfo l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2383
2465
|
} else {
|
|
2466
|
+
const rawTypeNum = Number(payload.Type);
|
|
2467
|
+
const isDisplayAd = rawTypeNum === 21 || rawTypeNum === 23 || rawTypeNum === 26 || adInfo.AdFormat === 1 || adInfo.AdFormat === 2 || adInfo.AdFormat === 6 || adInfo.AdFormat === 13 || adInfo.AdFormat === 14;
|
|
2384
2468
|
if (!adInfo.Caption || !adInfo.Caption.trim()) {
|
|
2385
|
-
|
|
2469
|
+
if (!isDisplayAd) {
|
|
2470
|
+
errors.push("Settings.AdInfo.Caption l\xE0 b\u1EAFt bu\u1ED9c.");
|
|
2471
|
+
}
|
|
2386
2472
|
} else {
|
|
2387
2473
|
const captionLen = adInfo.Caption.trim().length;
|
|
2388
|
-
if (captionLen < 35) {
|
|
2474
|
+
if (!isDisplayAd && captionLen < 35) {
|
|
2389
2475
|
errors.push(`Settings.AdInfo.Caption qu\xE1 ng\u1EAFn (${captionLen}/35 k\xFD t\u1EF1 t\u1ED1i thi\u1EC3u).`);
|
|
2390
2476
|
} else if (captionLen > 90) {
|
|
2391
2477
|
errors.push(`Settings.AdInfo.Caption qu\xE1 d\xE0i (${captionLen}/90 k\xFD t\u1EF1 t\u1ED1i \u0111a).`);
|
|
@@ -2409,6 +2495,14 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2409
2495
|
);
|
|
2410
2496
|
}
|
|
2411
2497
|
}
|
|
2498
|
+
if (isDisplayAd) {
|
|
2499
|
+
const targetUrl = typeof adInfo.TargetUrl === "object" ? adInfo.TargetUrl?.Url : adInfo.TargetUrl;
|
|
2500
|
+
if (!targetUrl || typeof targetUrl !== "string" || !targetUrl.trim()) {
|
|
2501
|
+
errors.push("Settings.AdInfo.TargetUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Display.");
|
|
2502
|
+
} else if (!/^https?:\/\//i.test(targetUrl.trim())) {
|
|
2503
|
+
errors.push("Settings.AdInfo.TargetUrl ph\u1EA3i l\xE0 m\u1ED9t \u0111\u01B0\u1EDDng d\u1EABn h\u1EE3p l\u1EC7 (b\u1EAFt \u0111\u1EA7u b\u1EB1ng http:// ho\u1EB7c https://).");
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2412
2506
|
if (adInfo.Action !== void 0 && payload.Type) {
|
|
2413
2507
|
const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];
|
|
2414
2508
|
if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {
|
|
@@ -2436,20 +2530,149 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2436
2530
|
} else if (payload.Type === VALID_AD_TYPES.VIDEO) {
|
|
2437
2531
|
if (price.Type !== 1 && price.Type !== 7) {
|
|
2438
2532
|
errors.push(
|
|
2439
|
-
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Type 11)
|
|
2533
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video (Type 11), Price.Type b\u1EAFt bu\u1ED9c l\xE0 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB) ho\u1EB7c 7 (CPV - L\u01B0\u1EE3t xem). N\u1EBFu truy\u1EC1n 2 (CPC), form ch\u1EC9nh s\u1EEDa c\u1EE7a Zalo Ads s\u1EBD kh\xF4ng hi\u1EC3n th\u1ECB \u0111\u01B0\u1EE3c gi\xE1 v\xE0 s\u1ED1 l\u01B0\u1EE3ng."
|
|
2440
2534
|
);
|
|
2441
2535
|
}
|
|
2442
|
-
if (price.Type === 1
|
|
2536
|
+
if (price.Type === 1) {
|
|
2537
|
+
if ((price.Limit ?? 0) < 50) {
|
|
2538
|
+
errors.push(
|
|
2539
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Video CPM, s\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB)."
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
const videoPlatform = payload.Settings?.VideoPlatform;
|
|
2543
|
+
if (videoPlatform === ZaloAdsVideoPlatform.VIDEO_NETWORK) {
|
|
2544
|
+
if (price.Bid !== void 0 && price.Bid < 7300) {
|
|
2545
|
+
errors.push(
|
|
2546
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho N\u1EC1n t\u1EA3ng Video (ZVideo, B\xE1o M\u1EDBi) t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2547
|
+
);
|
|
2548
|
+
}
|
|
2549
|
+
} else if (videoPlatform === ZaloAdsVideoPlatform.ZALO_FEED) {
|
|
2550
|
+
if (price.Bid !== void 0 && price.Bid < 6e3) {
|
|
2551
|
+
errors.push(
|
|
2552
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Video tr\xEAn Nh\u1EADt k\xFD Zalo t\u1ED1i thi\u1EC3u l\xE0 6,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2553
|
+
);
|
|
2554
|
+
}
|
|
2555
|
+
} else {
|
|
2556
|
+
if (price.Bid !== void 0 && price.Bid < 6e3) {
|
|
2557
|
+
errors.push(
|
|
2558
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Video t\u1ED1i thi\u1EC3u l\xE0 6,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
} else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
|
|
2564
|
+
if (price.Type !== 2 && price.Type !== 5) {
|
|
2443
2565
|
errors.push(
|
|
2444
|
-
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o
|
|
2566
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Commerce (Type 28), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng)."
|
|
2445
2567
|
);
|
|
2446
2568
|
}
|
|
2447
|
-
|
|
2569
|
+
if (price.Type === 2) {
|
|
2570
|
+
if (price.SpendingMethod === 1) {
|
|
2571
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 6e5) {
|
|
2572
|
+
errors.push(
|
|
2573
|
+
`T\u1ED5ng ng\xE2n s\xE1ch cho Qu\u1EA3ng c\xE1o Commerce CPC t\u1ED1i thi\u1EC3u l\xE0 600,000 VN\u0110 (Price.Limit >= 600000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2574
|
+
);
|
|
2575
|
+
}
|
|
2576
|
+
} else if (price.SpendingMethod === 0) {
|
|
2577
|
+
if (price.Bid !== void 0 && price.Bid < 650) {
|
|
2578
|
+
errors.push(
|
|
2579
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2580
|
+
);
|
|
2581
|
+
}
|
|
2582
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2583
|
+
errors.push(
|
|
2584
|
+
`S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2585
|
+
);
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
} else if (price.Type === 5) {
|
|
2589
|
+
if (price.SpendingMethod === 1) {
|
|
2590
|
+
if (price.Bid !== void 0 && price.Bid !== 0) {
|
|
2591
|
+
errors.push(
|
|
2592
|
+
"Khi ch\u1ECDn 'T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o' (SpendingMethod = 1) cho L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng (CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (h\u1EC7 th\u1ED1ng t\u1EF1 \u0111\u1ED9ng \u0111\u1EA5u th\u1EA7u)."
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 15e5) {
|
|
2596
|
+
errors.push(
|
|
2597
|
+
`T\u1ED5ng ng\xE2n s\xE1ch cho Qu\u1EA3ng c\xE1o Commerce CPA (L\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng t\u1EF1 \u0111\u1ED9ng) t\u1ED1i thi\u1EC3u l\xE0 1,500,000 VN\u0110 (Price.Limit >= 1500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2598
|
+
);
|
|
2599
|
+
}
|
|
2600
|
+
} else if (price.SpendingMethod === 0) {
|
|
2601
|
+
if (price.Bid !== void 0 && price.Bid < 6e4) {
|
|
2602
|
+
errors.push(
|
|
2603
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 60,000 VN\u0110 / l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
2606
|
+
if (price.Limit !== void 0 && price.Limit < 10) {
|
|
2607
|
+
errors.push(
|
|
2608
|
+
`S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t \u0111\u1EB7t h\xE0ng t\u1ED1i thi\u1EC3u (Price.Limit) l\xE0 10 \u0111\u01A1n h\xE0ng (Limit >= 10). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2609
|
+
);
|
|
2610
|
+
}
|
|
2611
|
+
} else if (price.SpendingMethod !== void 0) {
|
|
2612
|
+
errors.push(
|
|
2613
|
+
"C\xE1ch \u0111\u1EB7t gi\xE1 SpendingMethod cho Qu\u1EA3ng c\xE1o Commerce CPA ch\u1EC9 ch\u1EA5p nh\u1EADn 1 (T\u1ED5ng ng\xE2n s\xE1ch qu\u1EA3ng c\xE1o) ho\u1EB7c 0 (T\u1EF1 \u0111\u1EB7t gi\xE1)."
|
|
2614
|
+
);
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
} else if (payload.Type === VALID_AD_TYPES.ARTICLE) {
|
|
2448
2618
|
if (price.Type !== 2) {
|
|
2449
2619
|
errors.push(
|
|
2450
2620
|
`\u0110\u1ED1i v\u1EDBi Ad Type ${payload.Type}, Price.Type b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 2 (CPC).`
|
|
2451
2621
|
);
|
|
2452
2622
|
}
|
|
2623
|
+
} else if (payload.Type === VALID_AD_TYPES.FORM) {
|
|
2624
|
+
if (price.Type !== 1 && price.Type !== 2 && price.Type !== 5) {
|
|
2625
|
+
errors.push(
|
|
2626
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Type 18), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB), 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t li\xEAn h\u1EC7)."
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
if (price.Type === 1) {
|
|
2630
|
+
if (price.Bid !== void 0 && price.Bid < 7300) {
|
|
2631
|
+
errors.push(
|
|
2632
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Form t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2633
|
+
);
|
|
2634
|
+
}
|
|
2635
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2636
|
+
errors.push(
|
|
2637
|
+
`S\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Form CPM l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2638
|
+
);
|
|
2639
|
+
}
|
|
2640
|
+
} else if (price.Type === 2) {
|
|
2641
|
+
if (price.SpendingMethod === 1) {
|
|
2642
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 2e5) {
|
|
2643
|
+
errors.push(
|
|
2644
|
+
`Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Form CPC t\u1ED1i thi\u1EC3u l\xE0 200,000 VN\u0110 (Price.Limit >= 200000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2645
|
+
);
|
|
2646
|
+
}
|
|
2647
|
+
} else if (price.SpendingMethod === 0) {
|
|
2648
|
+
if (price.Bid !== void 0 && price.Bid < 650) {
|
|
2649
|
+
errors.push(
|
|
2650
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2654
|
+
errors.push(
|
|
2655
|
+
`S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2656
|
+
);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
} else if (price.Type === 5) {
|
|
2660
|
+
if (price.SpendingMethod !== 1) {
|
|
2661
|
+
errors.push(
|
|
2662
|
+
"Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (T\u1ED1i \u01B0u t\u1EF1 \u0111\u1ED9ng theo ng\xE2n s\xE1ch)."
|
|
2663
|
+
);
|
|
2664
|
+
}
|
|
2665
|
+
if (price.Bid !== void 0 && price.Bid !== 0) {
|
|
2666
|
+
errors.push(
|
|
2667
|
+
"Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (Zalo Ads t\u1EF1 \u0111\u1ED9ng t\u1ED1i \u01B0u gi\xE1 th\u1EA7u, n\u1EBFu truy\u1EC1n > 0 m\xE1y ch\u1EE7 s\u1EBD b\xE1o l\u1ED7i code 13: Gi\xE1 \u0111\u1EB7t kh\xF4ng h\u1EE3p l\u1EC7)."
|
|
2668
|
+
);
|
|
2669
|
+
}
|
|
2670
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 5e5) {
|
|
2671
|
+
errors.push(
|
|
2672
|
+
`Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Form CPA (L\u01B0\u1EE3t li\xEAn h\u1EC7) t\u1ED1i thi\u1EC3u l\xE0 500,000 VN\u0110 (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2453
2676
|
} else if (payload.Type === VALID_AD_TYPES.OA) {
|
|
2454
2677
|
if (price.Type !== 2 && price.Type !== 5) {
|
|
2455
2678
|
errors.push(
|
|
@@ -2509,13 +2732,43 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2509
2732
|
);
|
|
2510
2733
|
}
|
|
2511
2734
|
}
|
|
2512
|
-
} else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
2513
|
-
if (price.Type !== 2 && price.Type !== 5) {
|
|
2735
|
+
} else if (payload.Type === VALID_AD_TYPES.MESSAGE || payload.Type === VALID_AD_TYPES.MESSAGE_LEGACY || Number(payload.Type) === 19 || Number(payload.Type) === 30) {
|
|
2736
|
+
if (price.Type !== 1 && price.Type !== 2 && price.Type !== 5) {
|
|
2514
2737
|
errors.push(
|
|
2515
|
-
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin nh\u1EAFn (Type
|
|
2738
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin nh\u1EAFn (Type 19), Price.Type ch\u1EC9 h\u1ED7 tr\u1EE3 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB), 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n) ho\u1EB7c 5 (CPA - L\u01B0\u1EE3t li\xEAn h\u1EC7)."
|
|
2516
2739
|
);
|
|
2517
2740
|
}
|
|
2518
|
-
if (price.Type ===
|
|
2741
|
+
if (price.Type === 1) {
|
|
2742
|
+
if (price.Bid !== void 0 && price.Bid < 7300) {
|
|
2743
|
+
errors.push(
|
|
2744
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn t\u1ED1i thi\u1EC3u l\xE0 7,300 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2748
|
+
errors.push(
|
|
2749
|
+
`S\u1ED1 l\u01B0\u1EE3ng hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPM l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
} else if (price.Type === 2) {
|
|
2753
|
+
if (price.SpendingMethod === 1) {
|
|
2754
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 2e5) {
|
|
2755
|
+
errors.push(
|
|
2756
|
+
`Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPC t\u1ED1i thi\u1EC3u l\xE0 200,000 VN\u0110 (Price.Limit >= 200000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
} else if (price.SpendingMethod === 0) {
|
|
2760
|
+
if (price.Bid !== void 0 && price.Bid < 650) {
|
|
2761
|
+
errors.push(
|
|
2762
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) t\u1ED1i thi\u1EC3u l\xE0 650 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2763
|
+
);
|
|
2764
|
+
}
|
|
2765
|
+
if (price.Limit !== void 0 && price.Limit < 50) {
|
|
2766
|
+
errors.push(
|
|
2767
|
+
`S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) m\u1ED7i ng\xE0y l\xE0 50 l\u01B0\u1EE3t. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}.`
|
|
2768
|
+
);
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
} else if (price.Type === 5) {
|
|
2519
2772
|
if (price.SpendingMethod !== 1) {
|
|
2520
2773
|
errors.push(
|
|
2521
2774
|
"Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), SpendingMethod b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 1 (T\u1ED1i \u01B0u t\u1EF1 \u0111\u1ED9ng theo ng\xE2n s\xE1ch)."
|
|
@@ -2526,12 +2779,71 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2526
2779
|
"Khi t\xEDnh ti\u1EC1n theo L\u01B0\u1EE3t li\xEAn h\u1EC7 (Price.Type = 5 / CPA), tr\u01B0\u1EDDng Bid b\u1EAFt bu\u1ED9c ph\u1EA3i b\u1EB1ng 0 (Zalo Ads t\u1EF1 \u0111\u1ED9ng t\u1ED1i \u01B0u gi\xE1 th\u1EA7u, n\u1EBFu truy\u1EC1n > 0 m\xE1y ch\u1EE7 s\u1EBD b\xE1o l\u1ED7i code 13: Gi\xE1 \u0111\u1EB7t kh\xF4ng h\u1EE3p l\u1EC7)."
|
|
2527
2780
|
);
|
|
2528
2781
|
}
|
|
2782
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 5e5) {
|
|
2783
|
+
errors.push(
|
|
2784
|
+
`Ng\xE2n s\xE1ch m\u1ED7i ng\xE0y cho Qu\u1EA3ng c\xE1o Tin nh\u1EAFn CPA (L\u01B0\u1EE3t li\xEAn h\u1EC7) t\u1ED1i thi\u1EC3u l\xE0 500,000 VN\u0110 (Price.Limit >= 500000). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Limit}\u0111.`
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
} else if (Number(payload.Type) === 21 || Number(payload.Type) === 23 || Number(payload.Type) === 26 || payload.Type === VALID_AD_TYPES.DISPLAY || payload.Type === VALID_AD_TYPES.DISPLAY_HALFPAGE || payload.Type === VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE) {
|
|
2789
|
+
const adFormat = payload.Settings?.AdInfo?.AdFormat;
|
|
2790
|
+
const typeNum = Number(payload.Type);
|
|
2791
|
+
const isHalfpage = typeNum === 26 || adFormat === 13 || adFormat === 14 || (payload.AdName || "").toLowerCase().includes("halfpage");
|
|
2792
|
+
const isMediumRectangle = typeNum === 23 || adFormat === 6 || (payload.AdName || "").toLowerCase().includes("medium rectangle") || (payload.AdName || "").toLowerCase().includes("300x250");
|
|
2793
|
+
const adNameLower = (payload.AdName || "").toLowerCase();
|
|
2794
|
+
const isWelcome = adNameLower.includes("welcome");
|
|
2795
|
+
const isMasthead = (adNameLower.includes("masthead") || typeNum === 21 || adFormat === 1 || adFormat === 2) && !isWelcome && !isMediumRectangle;
|
|
2796
|
+
if (price.Type !== 1 && price.Type !== 2) {
|
|
2797
|
+
errors.push(
|
|
2798
|
+
"\u0110\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Display, Price.Type ch\u1EC9 ch\u1EA5p nh\u1EADn 1 (CPM - L\u01B0\u1EE3t hi\u1EC3n th\u1ECB) ho\u1EB7c 2 (CPC - L\u01B0\u1EE3t nh\u1EA5n)."
|
|
2799
|
+
);
|
|
2529
2800
|
}
|
|
2530
|
-
if (
|
|
2801
|
+
if ((isHalfpage || isMasthead) && price.Type === 2) {
|
|
2531
2802
|
errors.push(
|
|
2532
|
-
|
|
2803
|
+
`Qu\u1EA3ng c\xE1o ${isHalfpage ? "Halfpage (Type 26 / AdFormat 13, 14)" : "Masthead (Type 21)"} ch\u1EC9 h\u1ED7 tr\u1EE3 t\xEDnh ti\u1EC1n theo l\u01B0\u1EE3t hi\u1EC3n th\u1ECB CPM (Price.Type = 1), kh\xF4ng h\u1ED7 tr\u1EE3 CPC.`
|
|
2533
2804
|
);
|
|
2534
2805
|
}
|
|
2806
|
+
if (price.Type === 1) {
|
|
2807
|
+
if (price.Bid !== void 0) {
|
|
2808
|
+
if (isWelcome && price.Bid < 3e4) {
|
|
2809
|
+
errors.push(
|
|
2810
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Welcome Mobile t\u1ED1i thi\u1EC3u l\xE0 30,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2811
|
+
);
|
|
2812
|
+
} else if (isHalfpage && price.Bid < 16e3) {
|
|
2813
|
+
errors.push(
|
|
2814
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Halfpage t\u1ED1i thi\u1EC3u l\xE0 16,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2815
|
+
);
|
|
2816
|
+
} else if (isMasthead && price.Bid < 13e3) {
|
|
2817
|
+
errors.push(
|
|
2818
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Masthead t\u1ED1i thi\u1EC3u l\xE0 13,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2819
|
+
);
|
|
2820
|
+
} else if (isMediumRectangle && price.Bid < 8e3) {
|
|
2821
|
+
errors.push(
|
|
2822
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Medium Rectangle CPM t\u1ED1i thi\u1EC3u l\xE0 8,000 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2823
|
+
);
|
|
2824
|
+
} else if (price.Bid < 8e3) {
|
|
2825
|
+
errors.push(
|
|
2826
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i 1,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB (Price.Bid) cho Qu\u1EA3ng c\xE1o Display CPM t\u1ED1i thi\u1EC3u l\xE0 8,000 VN\u0110 (s\xE0n h\u1EC7 th\u1ED1ng). Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2827
|
+
);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
|
|
2831
|
+
errors.push(
|
|
2832
|
+
"S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t hi\u1EC3n th\u1ECB t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Display CPM l\xE0 50 (t\u01B0\u01A1ng \u1EE9ng 50,000 l\u01B0\u1EE3t hi\u1EC3n th\u1ECB)."
|
|
2833
|
+
);
|
|
2834
|
+
}
|
|
2835
|
+
} else if (price.Type === 2) {
|
|
2836
|
+
if (price.Bid !== void 0 && price.Bid < 1800) {
|
|
2837
|
+
errors.push(
|
|
2838
|
+
`Gi\xE1 \u0111\u1EB7t m\u1ED7i l\u01B0\u1EE3t nh\u1EA5n (Price.Bid) cho Qu\u1EA3ng c\xE1o Display CPC t\u1ED1i thi\u1EC3u l\xE0 1,800 VN\u0110. Hi\u1EC7n t\u1EA1i \u0111ang truy\u1EC1n: ${price.Bid}\u0111.`
|
|
2839
|
+
);
|
|
2840
|
+
}
|
|
2841
|
+
if (price.Limit !== void 0 && price.Limit > 0 && price.Limit < 50) {
|
|
2842
|
+
errors.push(
|
|
2843
|
+
"S\u1ED1 l\u01B0\u1EE3ng l\u01B0\u1EE3t nh\u1EA5n t\u1ED1i thi\u1EC3u (Price.Limit) cho Qu\u1EA3ng c\xE1o Display CPC l\xE0 50 l\u01B0\u1EE3t nh\u1EA5n."
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2535
2847
|
}
|
|
2536
2848
|
if (payload.Settings && payload.Settings.DeliveryType !== void 0) {
|
|
2537
2849
|
const deliveryType = payload.Settings.DeliveryType;
|
|
@@ -2548,6 +2860,21 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2548
2860
|
}
|
|
2549
2861
|
const targeting = payload.Settings?.Targeting;
|
|
2550
2862
|
if (targeting) {
|
|
2863
|
+
if (targeting.Gender !== void 0 && targeting.Gender !== null) {
|
|
2864
|
+
if (![0, 1, 2].includes(Number(targeting.Gender))) {
|
|
2865
|
+
errors.push(`M\xE3 gi\u1EDBi t\xEDnh 'Gender' (${targeting.Gender}) kh\xF4ng h\u1EE3p l\u1EC7. H\u1EE3p l\u1EC7: 0 (T\u1EA5t c\u1EA3), 1 (Nam), 2 (N\u1EEF).`);
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
if (targeting.CustomAudienceId !== void 0 && targeting.CustomAudienceId !== null) {
|
|
2869
|
+
if (typeof targeting.CustomAudienceId !== "number" || targeting.CustomAudienceId < 0) {
|
|
2870
|
+
errors.push("CustomAudienceId ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn kh\xF4ng \xE2m (>= 0).");
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
if (targeting.ExcludedAudienceId !== void 0 && targeting.ExcludedAudienceId !== null) {
|
|
2874
|
+
if (typeof targeting.ExcludedAudienceId !== "number" || targeting.ExcludedAudienceId < 0) {
|
|
2875
|
+
errors.push("ExcludedAudienceId ph\u1EA3i l\xE0 s\u1ED1 nguy\xEAn kh\xF4ng \xE2m (>= 0).");
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2551
2878
|
const newAges = targeting.NewAgeRanges;
|
|
2552
2879
|
const oldAges = targeting.AgeRanges;
|
|
2553
2880
|
if (newAges && newAges.length > 0) {
|
|
@@ -2571,6 +2898,14 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2571
2898
|
errors.push(`M\xE3 h\u1EC7 \u0111i\u1EC1u h\xE0nh kh\xF4ng h\u1EE3p l\u1EC7: ${invalidOs.join(", ")}. H\u1EE3p l\u1EC7: 0 (Android), 1 (iOS), 3 (PC).`);
|
|
2572
2899
|
}
|
|
2573
2900
|
}
|
|
2901
|
+
const videoPlatform = payload.Settings?.VideoPlatform;
|
|
2902
|
+
if (videoPlatform !== void 0 && videoPlatform !== null) {
|
|
2903
|
+
if (![1, 2].includes(Number(videoPlatform))) {
|
|
2904
|
+
warnings.push(
|
|
2905
|
+
`VideoPlatform (${videoPlatform}) kh\xF4ng h\u1EE3p l\u1EC7. Gi\xE1 tr\u1ECB chu\u1EA9n: 1 (N\u1EC1n t\u1EA3ng Video - ZVideo, B\xE1o M\u1EDBi) ho\u1EB7c 2 (Nh\u1EADt k\xFD Zalo - Feed).`
|
|
2906
|
+
);
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2574
2909
|
const deliveryType = payload.Settings?.DeliveryType;
|
|
2575
2910
|
if (deliveryType !== void 0 && deliveryType !== ZaloAdsDeliveryType.STANDARD && deliveryType !== ZaloAdsDeliveryType.SPEED_UP) {
|
|
2576
2911
|
warnings.push(
|
|
@@ -2638,21 +2973,15 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2638
2973
|
if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {
|
|
2639
2974
|
errors.push("ZaloFormId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Form (Ad Type 18).");
|
|
2640
2975
|
}
|
|
2641
|
-
} else if (payload.Type === VALID_AD_TYPES.MESSAGE) {
|
|
2976
|
+
} else if (payload.Type === VALID_AD_TYPES.MESSAGE || payload.Type === VALID_AD_TYPES.MESSAGE_LEGACY || Number(payload.Type) === 19 || Number(payload.Type) === 30) {
|
|
2642
2977
|
if (!payload.Settings?.Image?.LogoUrl) {
|
|
2643
|
-
errors.push("Settings.Image.LogoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30).");
|
|
2644
|
-
}
|
|
2645
|
-
if (!payload.MiniPageId || payload.MiniPageId <= 0) {
|
|
2646
|
-
errors.push(
|
|
2647
|
-
"MiniPageId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 30, Template 4 - K\u1ECBch b\u1EA3n gi\u1EDBi thi\u1EC7u th\u01B0\u01A1ng hi\u1EC7u / Tin nh\u1EAFn). N\u1EBFu thi\u1EBFu ho\u1EB7c = 0, m\xE1y ch\u1EE7 Zalo Ads s\u1EBD t\u1EEB ch\u1ED1i v\u1EDBi l\u1ED7i: 'Mini Page kh\xF4ng h\u1EE3p l\u1EC7.'."
|
|
2648
|
-
);
|
|
2978
|
+
errors.push("Settings.Image.LogoUrl l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn (Ad Type 19/30).");
|
|
2649
2979
|
}
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
if (payload.Settings?.Image?.ExtraImgs && payload.Settings?.Image?.ExtraImgs.length > 0) {
|
|
2980
|
+
const hasFlow = payload.ZaloFlowId && Number(payload.ZaloFlowId) > 0;
|
|
2981
|
+
const hasMiniPage = payload.MiniPageId && Number(payload.MiniPageId) > 0;
|
|
2982
|
+
if (!hasFlow && !hasMiniPage) {
|
|
2654
2983
|
errors.push(
|
|
2655
|
-
"Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn \
|
|
2984
|
+
"Qu\u1EA3ng c\xE1o Tin Nh\u1EAFn y\xEAu c\u1EA7u ph\u1EA3i ch\u1ECDn K\u1ECBch b\u1EA3n tin nh\u1EAFn (ZaloFlowId > 0) ho\u1EB7c Trang gi\u1EDBi thi\u1EC7u th\u01B0\u01A1ng hi\u1EC7u (MiniPageId > 0)."
|
|
2656
2985
|
);
|
|
2657
2986
|
}
|
|
2658
2987
|
} else if (payload.Type === VALID_AD_TYPES.COMMERCE) {
|
|
@@ -2670,6 +2999,14 @@ function validateUpdateAdPayload(payload, options = {}) {
|
|
|
2670
2999
|
if (!payload.ZaloFeedId && !payload.articleId) {
|
|
2671
3000
|
errors.push("ZaloFeedId ho\u1EB7c articleId l\xE0 b\u1EAFt bu\u1ED9c \u0111\u1ED1i v\u1EDBi Qu\u1EA3ng c\xE1o B\xE0i Vi\u1EBFt (Ad Type 3).");
|
|
2672
3001
|
}
|
|
3002
|
+
} else if (Number(payload.Type) === 21 || Number(payload.Type) === 23 || Number(payload.Type) === 26 || payload.Type === VALID_AD_TYPES.DISPLAY || payload.Type === VALID_AD_TYPES.DISPLAY_HALFPAGE || payload.Type === VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE) {
|
|
3003
|
+
const img = payload.Settings?.Image;
|
|
3004
|
+
const hasImage = img?.LandscapeCoverUrl || img?.BaseLandscapeCoverUrl || img?.PortraitCoverUrl || img?.SquareCoverUrl;
|
|
3005
|
+
if (!hasImage) {
|
|
3006
|
+
errors.push(
|
|
3007
|
+
"Qu\u1EA3ng c\xE1o Display b\u1EAFt bu\u1ED9c ph\u1EA3i c\xF3 \xEDt nh\u1EA5t m\u1ED9t banner h\xECnh \u1EA3nh (Settings.Image.LandscapeCoverUrl ho\u1EB7c BaseLandscapeCoverUrl)."
|
|
3008
|
+
);
|
|
3009
|
+
}
|
|
2673
3010
|
}
|
|
2674
3011
|
return {
|
|
2675
3012
|
isValid: errors.length === 0,
|
|
@@ -2911,7 +3248,19 @@ function validateUpdateWebsiteAd(payload, options = {}) {
|
|
|
2911
3248
|
return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.WEBSITE }, options);
|
|
2912
3249
|
}
|
|
2913
3250
|
function validateUpdateDisplayAd(payload, options = {}) {
|
|
2914
|
-
|
|
3251
|
+
const adFormat = payload.Settings?.AdInfo?.AdFormat;
|
|
3252
|
+
const rawType = Number(payload.Type);
|
|
3253
|
+
const isHalfpage = rawType === 26 || adFormat === 13 || adFormat === 14;
|
|
3254
|
+
const isMediumRectangle = rawType === 23 || adFormat === 6;
|
|
3255
|
+
let effectiveType;
|
|
3256
|
+
if (isHalfpage) {
|
|
3257
|
+
effectiveType = VALID_AD_TYPES.DISPLAY_HALFPAGE;
|
|
3258
|
+
} else if (isMediumRectangle) {
|
|
3259
|
+
effectiveType = VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE;
|
|
3260
|
+
} else {
|
|
3261
|
+
effectiveType = payload.Type ?? VALID_AD_TYPES.DISPLAY;
|
|
3262
|
+
}
|
|
3263
|
+
return validateUpdateAdPayload({ ...payload, Type: effectiveType }, options);
|
|
2915
3264
|
}
|
|
2916
3265
|
function validateUpdateVideoAd(payload, options = {}) {
|
|
2917
3266
|
return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.VIDEO }, options);
|
|
@@ -9058,6 +9407,7 @@ var ZaloMediaValidator = {
|
|
|
9058
9407
|
VALID_AD_TYPES,
|
|
9059
9408
|
VALID_CAMPAIGN_TYPES,
|
|
9060
9409
|
VIETNAM_PHONE_REGEX,
|
|
9410
|
+
ZALO_DISPLAY_AD_FORMAT,
|
|
9061
9411
|
ZALO_NEW_REGION_PROVINCE_CODES,
|
|
9062
9412
|
ZALO_PROFILE_ADS_PROVINCES,
|
|
9063
9413
|
ZALO_PROFILE_ADS_SUB_CATEGORIES,
|
|
@@ -9093,6 +9443,7 @@ var ZaloMediaValidator = {
|
|
|
9093
9443
|
ZaloAdsUpdateVideoAdRequest,
|
|
9094
9444
|
ZaloAdsUpdateVideoAdResponse,
|
|
9095
9445
|
ZaloAdsUseConversion,
|
|
9446
|
+
ZaloAdsVideoPlatform,
|
|
9096
9447
|
ZaloAdsVideoSrc,
|
|
9097
9448
|
ZaloAdsXTemplates,
|
|
9098
9449
|
ZaloAudiencesService,
|