Lewati ke konten utama
Versi: 0.8.0

Kategori Berita

API Kategori Berita menyediakan akses ke sistem klasifikasi dan organisasi yang digunakan oleh BPS (Badan Pusat Statistik) Indonesia untuk mengkategorikan konten berita dan komunikasi resmi. Kategori berita berfungsi sebagai kerangka kerja organisasi yang memungkinkan navigasi, penemuan, dan analisis konten yang efisien di seluruh ekosistem komunikasi BPS.

Kategori berita BPS memainkan peran penting dalam struktur informasi, memungkinkan audiens mengakses konten yang relevan dengan minat atau kebutuhan spesifik mereka, sekaligus memfasilitasi analisis tematik dan pemantauan tren komunikasi di berbagai domain statistik.

Memahami Sistem Kategori Berita BPS

Kategori berita menyediakan struktur organisasi untuk navigasi konten:

  • Klasifikasi Tematik: Pengelompokan sistematis berita berdasarkan topik dan area subjek statistik
  • Navigasi Efisien: Struktur kategori yang memfasilitasi penemuan konten yang ditargetkan
  • Analisis Lintas-Domain: Kemampuan untuk membandingkan cakupan topik di berbagai wilayah geografis
  • Organisasi Konten: Kerangka kerja untuk mengelola dan mengkurasi konten berita dalam volume besar
  • Konsistensi Editorial: Standarisasi kategorisasi untuk mempertahankan konsistensi di seluruh saluran komunikasi

Struktur Sistem Kategori Berita

Kategori berita BPS dirancang untuk kemudahan penggunaan dan organisasi:

  • Hierarki Kategori: Struktur organisasi yang mendukung navigasi dari umum ke spesifik
  • Cakupan Geografis: Kategori tersedia di berbagai tingkat administratif dan wilayah
  • Fleksibilitas Konten: Dukungan untuk berbagai jenis konten dan format komunikasi
  • Integrasi Sistem: Kompatibilitas dengan sistem manajemen konten dan alur kerja editorial
  • Skalabilitas: Struktur yang dapat berkembang dengan kebutuhan komunikasi yang berubah

Parameter

ParameterTipeDeskripsi
domainStringKode domain (wilayah) untuk mengambil kategori berita (wajib)
langDataLanguageBahasa untuk data kategori berita (default: DataLanguage.id)

Contoh

1. Mengambil Semua Kategori Berita untuk Domain

// Mengambil kategori berita dari BPS Jawa Tengah
final result = await StadataFlutter.instance.list.newsCategories(
domain: '3300', // Kode domain Jawa Tengah
lang: DataLanguage.id,
);

final daftarKategoriBerita = result.data;
final paginasi = result.pagination;

// Menampilkan informasi paginasi
print('Halaman Saat Ini: ${paginasi.page}');
print('Total Halaman: ${paginasi.pages}');
print('Jumlah Data pada Halaman Ini: ${paginasi.count}');
print('Per Halaman: ${paginasi.perPage}');
print('Total: ${paginasi.total}');
print('------------------------');

// Menampilkan data kategori berita yang diperoleh
for (final kategoriBerita in daftarKategoriBerita) {
print('ID Kategori Berita: ${kategoriBerita.id}');
print('Nama Kategori Berita: ${kategoriBerita.name}');

// Menganalisis jenis kategori berdasarkan nama
final categoryName = kategoriBerita.name.toLowerCase();
if (categoryName.contains('ekonomi')) {
print(' Tipe: Kategori ekonomi dan keuangan');
} else if (categoryName.contains('sosial') || categoryName.contains('demografi')) {
print(' Tipe: Kategori sosial dan demografi');
} else if (categoryName.contains('regional') || categoryName.contains('daerah')) {
print(' Tipe: Kategori regional dan pembangunan');
} else if (categoryName.contains('metodologi') || categoryName.contains('teknis')) {
print(' Tipe: Kategori metodologi dan teknis');
} else {
print(' Tipe: Kategori umum');
}

print('------------------------');
}

2. Menganalisis Distribusi Kategori di Berbagai Domain

// Membandingkan kategori berita di berbagai wilayah
class NewsCategoryAnalyzer {
static Future<void> analyzeCategoriesAcrossDomains() async {
final domains = ['0000', '3100', '3200', '3300']; // Nasional, Jakarta, Jawa Barat, Jawa Tengah
final domainCategories = <String, List<NewsCategory>>{};

for (final domain in domains) {
final categories = await StadataFlutter.instance.list.newsCategories(
domain: domain,
lang: DataLanguage.id,
);
domainCategories[domain] = categories.data;

await Future.delayed(Duration(milliseconds: 300));
}

print('=== Analisis Distribusi Kategori Berita ===');
for (final entry in domainCategories.entries) {
print('Domain ${entry.key}: ${entry.value.length} kategori');

// Menganalisis jenis kategori
final categoryTypes = <String, int>{};
for (final category in entry.value) {
final categoryName = category.name.toLowerCase();
String type;

if (categoryName.contains('ekonomi') || categoryName.contains('keuangan')) {
type = 'Ekonomi';
} else if (categoryName.contains('sosial') || categoryName.contains('demografi')) {
type = 'Sosial';
} else if (categoryName.contains('regional') || categoryName.contains('daerah')) {
type = 'Regional';
} else if (categoryName.contains('metodologi') || categoryName.contains('teknis')) {
type = 'Metodologi';
} else {
type = 'Umum';
}

categoryTypes[type] = (categoryTypes[type] ?? 0) + 1;
}

print(' Distribusi jenis kategori:');
for (final typeEntry in categoryTypes.entries) {
print(' ${typeEntry.key}: ${typeEntry.value} kategori');
}

// Menampilkan contoh kategori
print(' Contoh kategori:');
for (final category in entry.value.take(3)) {
print(' • ${category.name} (ID: ${category.id})');
}

print('---');
}
}
}

3. Sistem Navigasi Berbasis Kategori

// Sistem navigasi kategori untuk akses konten yang efisien
class CategoryNavigationSystem {
static Future<void> buildCategoryNavigation(String domain) async {
try {
// 1. Mengambil semua kategori untuk domain
final categories = await StadataFlutter.instance.list.newsCategories(
domain: domain,
lang: DataLanguage.id,
);

print('=== Sistem Navigasi Kategori ===');
print('Total kategori di domain $domain: ${categories.data.length}');

// 2. Mengelompokkan kategori berdasarkan tema
final thematicGroups = <String, List<NewsCategory>>{
'Ekonomi dan Keuangan': [],
'Sosial dan Demografi': [],
'Regional dan Pembangunan': [],
'Metodologi dan Teknis': [],
'Umum dan Lainnya': [],
};

for (final category in categories.data) {
final categoryName = category.name.toLowerCase();

if (categoryName.contains('ekonomi') || categoryName.contains('keuangan') ||
categoryName.contains('inflasi') || categoryName.contains('pdb')) {
thematicGroups['Ekonomi dan Keuangan']!.add(category);
} else if (categoryName.contains('sosial') || categoryName.contains('demografi') ||
categoryName.contains('penduduk') || categoryName.contains('kemiskinan')) {
thematicGroups['Sosial dan Demografi']!.add(category);
} else if (categoryName.contains('regional') || categoryName.contains('daerah') ||
categoryName.contains('provinsi') || categoryName.contains('kabupaten')) {
thematicGroups['Regional dan Pembangunan']!.add(category);
} else if (categoryName.contains('metodologi') || categoryName.contains('teknis') ||
categoryName.contains('survei') || categoryName.contains('sensus')) {
thematicGroups['Metodologi dan Teknis']!.add(category);
} else {
thematicGroups['Umum dan Lainnya']!.add(category);
}
}

// 3. Membangun navigasi hierarkis
print('\\n=== Struktur Navigasi Hierarkis ===');
for (final entry in thematicGroups.entries) {
final themeName = entry.key;
final themeCategories = entry.value;

if (themeCategories.isNotEmpty) {
print('📁 $themeName (${themeCategories.length} kategori)');

for (final category in themeCategories) {
print(' └── ${category.name} (ID: ${category.id})');
}

print('');
}
}

// 4. Statistik navigasi
final totalThemes = thematicGroups.values.where((list) => list.isNotEmpty).length;
final averageCategoriesPerTheme = categories.data.length / totalThemes;

print('=== Statistik Navigasi ===');
print('Tema dengan kategori: $totalThemes');
print('Rata-rata kategori per tema: ${averageCategoriesPerTheme.toStringAsFixed(1)}');

// Menentukan tema dominan
final dominantTheme = thematicGroups.entries
.where((entry) => entry.value.isNotEmpty)
.reduce((a, b) => a.value.length > b.value.length ? a : b);

print('Tema dominan: ${dominantTheme.key} (${dominantTheme.value.length} kategori)');

} catch (e) {
print('Error membangun navigasi: $e');
}
}
}

4. Analisis Penggunaan Kategori dan Optimisasi

// Sistem analisis untuk mengoptimalkan penggunaan kategori
class CategoryUsageAnalyzer {
static Future<void> analyzeCategoryUsage(String domain) async {
try {
// 1. Mengambil kategori berita
final categories = await StadataFlutter.instance.list.newsCategories(
domain: domain,
lang: DataLanguage.id,
);

// 2. Mengambil berita untuk analisis penggunaan
final news = await StadataFlutter.instance.list.news(
domain: domain,
lang: DataLanguage.id,
);

print('=== Analisis Penggunaan Kategori ===');
print('Total kategori: ${categories.data.length}');
print('Total berita: ${news.data.length}');

// 3. Menganalisis penggunaan kategori
final categoryUsage = <String, int>{};
for (final newsItem in news.data) {
final categoryId = newsItem.categoryId;
categoryUsage[categoryId] = (categoryUsage[categoryId] ?? 0) + 1;
}

print('Kategori yang digunakan: ${categoryUsage.keys.length}');

// 4. Menganalisis efektivitas kategori
final sortedUsage = categoryUsage.entries.toList()
..sort((a, b) => b.value.compareTo(a.value));

print('\\n=== Ranking Penggunaan Kategori ===');
for (final entry in sortedUsage.take(10)) {
final categoryId = entry.key;
final usageCount = entry.value;

final category = categories.data
.where((cat) => cat.id == categoryId)
.firstOrNull;

final categoryName = category?.name ?? 'Kategori $categoryId';
final usagePercentage = (usageCount / news.data.length * 100);

print('${sortedUsage.indexOf(entry) + 1}. $categoryName');
print(' Penggunaan: $usageCount berita (${usagePercentage.toStringAsFixed(1)}%)');
}

// 5. Mengidentifikasi kategori yang tidak digunakan
final unusedCategories = categories.data
.where((cat) => !categoryUsage.containsKey(cat.id))
.toList();

if (unusedCategories.isNotEmpty) {
print('\\n=== Kategori Tidak Digunakan ===');
print('Jumlah: ${unusedCategories.length}');
for (final category in unusedCategories.take(5)) {
print(' • ${category.name} (ID: ${category.id})');
}
}

// 6. Rekomendasi optimisasi
print('\\n=== Rekomendasi Optimisasi ===');
final utilizationRate = (categoryUsage.keys.length / categories.data.length);

if (utilizationRate < 0.5) {
print('Tingkat pemanfaatan rendah (${(utilizationRate * 100).toStringAsFixed(1)}%)');
print('Rekomendasi: Evaluasi dan konsolidasi kategori yang tidak digunakan');
} else if (utilizationRate < 0.8) {
print('Tingkat pemanfaatan sedang (${(utilizationRate * 100).toStringAsFixed(1)}%)');
print('Rekomendasi: Optimalkan distribusi konten ke kategori yang kurang digunakan');
} else {
print('Tingkat pemanfaatan tinggi (${(utilizationRate * 100).toStringAsFixed(1)}%)');
print('Rekomendasi: Sistem kategori sudah optimal');
}

// Analisis konsentrasi konten
final top3Usage = sortedUsage.take(3).map((e) => e.value).reduce((a, b) => a + b);
final concentrationRatio = top3Usage / news.data.length;

if (concentrationRatio > 0.7) {
print('Konsentrasi konten tinggi pada 3 kategori teratas (${(concentrationRatio * 100).toStringAsFixed(1)}%)');
print('Rekomendasi: Diversifikasi konten ke kategori lain untuk keseimbangan');
}

} catch (e) {
print('Error analisis penggunaan: $e');
}
}
}

5. Sistem Manajemen Kategori Lintas-Domain

// Sistem manajemen kategori yang komprehensif untuk analisis lintas-domain
class CrossDomainCategoryManager {
static Future<void> manageCategoriesAcrossDomains() async {
try {
// 1. Mengambil kategori dari beberapa domain utama
final domains = ['0000', '3100', '3200', '3300', '6100']; // Nasional + provinsi utama
final domainCategoryData = <String, Map<String, dynamic>>{};

for (final domain in domains) {
final categories = await StadataFlutter.instance.list.newsCategories(
domain: domain,
lang: DataLanguage.id,
);

final news = await StadataFlutter.instance.list.news(
domain: domain,
lang: DataLanguage.id,
);

// Menganalisis penggunaan kategori per domain
final categoryUsage = <String, int>{};
for (final newsItem in news.data) {
categoryUsage[newsItem.categoryId] = (categoryUsage[newsItem.categoryId] ?? 0) + 1;
}

domainCategoryData[domain] = {
'categories': categories.data,
'news': news.data,
'usage': categoryUsage,
};

await Future.delayed(Duration(milliseconds: 200));
}

print('=== Manajemen Kategori Lintas-Domain ===');

// 2. Menganalisis konsistensi kategori
final allCategoryNames = <String, Set<String>>{};
for (final entry in domainCategoryData.entries) {
final domain = entry.key;
final categories = entry.value['categories'] as List<NewsCategory>;

for (final category in categories) {
allCategoryNames[category.name] = (allCategoryNames[category.name] ?? <String>{})..add(domain);
}
}

// Mencari kategori yang konsisten di semua domain
final universalCategories = allCategoryNames.entries
.where((entry) => entry.value.length >= domains.length - 1) // Ada di hampir semua domain
.map((entry) => entry.key)
.toList();

print('Kategori universal (ada di hampir semua domain): ${universalCategories.length}');
for (final categoryName in universalCategories.take(5)) {
print(' • $categoryName');
}

// 3. Menganalisis kategori unik per domain
print('\\n=== Kategori Unik per Domain ===');
for (final entry in domainCategoryData.entries) {
final domain = entry.key;
final categories = entry.value['categories'] as List<NewsCategory>;

final uniqueCategories = categories
.where((cat) => allCategoryNames[cat.name]!.length == 1)
.toList();

print('Domain $domain: ${uniqueCategories.length} kategori unik');
for (final category in uniqueCategories.take(3)) {
print(' • ${category.name}');
}
}

// 4. Menganalisis efektivitas penggunaan
print('\\n=== Efektivitas Penggunaan ===');
for (final entry in domainCategoryData.entries) {
final domain = entry.key;
final categories = entry.value['categories'] as List<NewsCategory>;
final usage = entry.value['usage'] as Map<String, int>;
final newsCount = (entry.value['news'] as List).length;

final utilizationRate = usage.keys.length / categories.length;
final avgNewsPerCategory = newsCount / categories.length;

print('Domain $domain:');
print(' Tingkat pemanfaatan: ${(utilizationRate * 100).toStringAsFixed(1)}%');
print(' Rata-rata berita per kategori: ${avgNewsPerCategory.toStringAsFixed(1)}');

// Mencari kategori paling aktif
if (usage.isNotEmpty) {
final mostActiveCategory = usage.entries
.reduce((a, b) => a.value > b.value ? a : b);

final categoryName = categories
.where((cat) => cat.id == mostActiveCategory.key)
.map((cat) => cat.name)
.firstOrNull ?? 'Kategori ${mostActiveCategory.key}';

print(' Kategori teraktif: $categoryName (${mostActiveCategory.value} berita)');
}

print('');
}

// 5. Rekomendasi standardisasi
print('=== Rekomendasi Standardisasi ===');
final totalDomains = domains.length;
final consistentCategories = universalCategories.length;
final consistencyRate = consistentCategories / allCategoryNames.length;

print('Tingkat konsistensi kategori: ${(consistencyRate * 100).toStringAsFixed(1)}%');

if (consistencyRate < 0.6) {
print('Rekomendasi: Perlu standardisasi kategori lintas-domain');
print('Fokus pada harmonisasi kategori universal dan pengurangan fragmentasi');
} else if (consistencyRate < 0.8) {
print('Rekomendasi: Tingkatkan konsistensi dengan menyelaraskan kategori utama');
} else {
print('Rekomendasi: Sistem kategori sudah konsisten, pertahankan standar');
}

} catch (e) {
print('Error manajemen lintas-domain: $e');
}
}
}

Properti (NewsCategory)

PropertiTipeDeskripsi
idStringPengidentifikasi unik untuk kategori berita
nameStringNama kategori berita

Kategori Berita BPS Umum

Kategori Ekonomi dan Keuangan

  • Statistik Ekonomi: Kategori untuk berita tentang PDB, pertumbuhan ekonomi, dan indikator makroekonomi
  • Inflasi dan Harga: Kategori khusus untuk berita tentang inflasi, indeks harga, dan daya beli
  • Perdagangan: Kategori untuk berita ekspor-impor, neraca perdagangan, dan kerjasama ekonomi
  • Ketenagakerjaan: Kategori untuk berita tentang tingkat pengangguran, angkatan kerja, dan produktivitas

Kategori Sosial dan Demografi

  • Kependudukan: Kategori untuk berita tentang sensus penduduk, dinamika demografi, dan migrasi
  • Kesejahteraan Sosial: Kategori untuk berita tentang kemiskinan, kesejahteraan, dan program sosial
  • Pendidikan: Kategori untuk berita tentang statistik pendidikan, literasi, dan akses pendidikan
  • Kesehatan: Kategori untuk berita tentang statistik kesehatan, akses layanan, dan indikator kesehatan

Kategori Regional dan Pembangunan

  • Pembangunan Daerah: Kategori untuk berita tentang capaian pembangunan regional dan lokal
  • Statistik Provinsi: Kategori khusus untuk berita tingkat provinsi dan perbandingan antar daerah
  • Infrastruktur: Kategori untuk berita tentang pembangunan infrastruktur dan fasilitas publik
  • Lingkungan: Kategori untuk berita tentang statistik lingkungan dan keberlanjutan

Kategori Metodologi dan Teknis

  • Metodologi Survei: Kategori untuk berita tentang metode pengumpulan data dan survei baru
  • Inovasi Statistik: Kategori untuk berita tentang teknologi dan inovasi dalam sistem statistik
  • Standarisasi: Kategori untuk berita tentang adopsi standar dan harmonisasi data
  • Pelatihan dan Pengembangan: Kategori untuk berita tentang capacity building dan pengembangan SDM

Alur Kerja Manajemen Kategori

Alur kerja tipikal untuk menggunakan kategori berita secara efektif:

  1. Eksplorasi Kategori: Temukan kategori yang tersedia untuk domain yang diminati
  2. Analisis Distribusi: Pahami distribusi kategori dan penggunaannya dalam konten
  3. Navigasi Tematik: Gunakan kategori untuk filtering dan penemuan konten yang ditargetkan
  4. Optimisasi Penggunaan: Evaluasi efektivitas kategori dan identifikasi area untuk perbaikan
  5. Standardisasi Lintas-Domain: Harmonisasi kategori untuk konsistensi antar wilayah

Integrasi dengan API Lain

Membangun Sistem Manajemen Konten Berbasis Kategori

// Mengintegrasikan kategori berita dengan sistem manajemen konten
Future<void> buildCategoryBasedContentSystem(String domain) async {
try {
// Mendapatkan informasi domain
final domains = await StadataFlutter.instance.list.domains();
final currentDomain = domains.data.firstWhere((d) => d.id == domain);

// Mendapatkan kategori berita
final categories = await StadataFlutter.instance.list.newsCategories(
domain: domain,
lang: DataLanguage.id,
);

// Mendapatkan berita untuk setiap kategori
final categoryContentMap = <String, List<News>>{};

for (final category in categories.data) {
final categoryNews = await StadataFlutter.instance.list.news(
domain: domain,
newsCategoryId: category.id,
lang: DataLanguage.id,
);

categoryContentMap[category.id] = categoryNews.data;
await Future.delayed(Duration(milliseconds: 200));
}

print('=== Sistem Manajemen Konten Berbasis Kategori ===');
print('Domain: ${currentDomain.name}');
print('Total Kategori: ${categories.data.length}');

// Analisis distribusi konten per kategori
print('\\n=== Distribusi Konten per Kategori ===');
final sortedCategories = categories.data.toList()
..sort((a, b) => (categoryContentMap[b.id]?.length ?? 0)
.compareTo(categoryContentMap[a.id]?.length ?? 0));

for (final category in sortedCategories.take(10)) {
final contentCount = categoryContentMap[category.id]?.length ?? 0;
print('${category.name}: $contentCount berita');

// Analisis tren konten terbaru
if (contentCount > 0) {
final recentContent = categoryContentMap[category.id]!
.where((news) => news.releaseDate.isAfter(
DateTime.now().subtract(Duration(days: 30))))
.length;

print(' Konten 30 hari terakhir: $recentContent');

// Analisis gambar dalam konten
final contentWithImages = categoryContentMap[category.id]!
.where((news) => news.picture.isNotEmpty)
.length;

print(' Dengan gambar: $contentWithImages');
}

print('');
}

// Rekomendasi manajemen konten
print('=== Rekomendasi Manajemen Konten ===');
final totalContent = categoryContentMap.values
.map((list) => list.length)
.reduce((a, b) => a + b);

final activeCategories = categoryContentMap.entries
.where((entry) => entry.value.isNotEmpty)
.length;

final averageContentPerCategory = totalContent / activeCategories;

print('Total konten: $totalContent berita');
print('Kategori aktif: $activeCategories dari ${categories.data.length}');
print('Rata-rata konten per kategori aktif: ${averageContentPerCategory.toStringAsFixed(1)}');

if (averageContentPerCategory < 5) {
print('Rekomendasi: Tingkatkan produksi konten atau konsolidasi kategori');
} else if (averageContentPerCategory > 20) {
print('Rekomendasi: Pertimbangkan sub-kategorisasi untuk navigasi yang lebih baik');
} else {
print('Rekomendasi: Distribusi konten sudah seimbang');
}

} catch (e) {
print('Error pembuatan sistem manajemen konten: $e');
}
}

Penanganan Error

Metode API Kategori Berita mengembalikan Future<ListResult<NewsCategory>> dan dapat menimbulkan exception spesifik:

  • NewsCategoryException: Error terkait kategori berita (domain tidak valid)
  • ApiException: Error terkait jaringan atau API
  • ApiKeyNotFoundException: API key tidak valid atau hilang
try {
final result = await StadataFlutter.instance.list.newsCategories(
domain: '3200',
lang: DataLanguage.id,
);

// Memproses hasil yang berhasil
print('Ditemukan ${result.data.length} kategori berita');

} on NewsCategoryException catch (e) {
print('Error kategori berita: ${e.message}');
// Menangani error validasi domain atau masalah kategori

} on ApiException catch (e) {
print('Error API: ${e.message}');
// Menangani error konektivitas jaringan atau layanan API

} catch (e) {
print('Error tidak terduga: $e');
// Menangani error tak terduga lainnya
}

Pertimbangan Performa

  • Caching Kategori: Cache kategori yang stabil untuk mengurangi beban API
  • Analisis Batch: Proses analisis kategori secara batch untuk efisiensi
  • Optimisasi Navigasi: Implementasikan navigasi hierarkis untuk kategori yang kompleks
  • Manajemen State: Pertahankan state kategori yang dipilih untuk pengalaman pengguna yang konsisten
  • Lazy Loading: Implementasikan lazy loading untuk konten kategori dengan volume besar
  • Sinkronisasi: Sinkronisasi kategori secara periodik untuk mempertahankan konsistensi data