Build in Public · LF-07
Multiplatform Reputation Monitoring Blueprint: Define Scope Before Evaluating Negative Shifts
Design a traceable reputation monitoring workflow starting with target lists, comment identities, and incremental cursors; use offline samples to demonstrate deduplication and ingestion gaps while preserving manual review.
Receiving more negative comments yesterday and fewer today does not directly indicate improved brand reputation. If today's ingestion missed a set of locations, a platform failed, or the same comment was counted twice, the figures from the two days are incomparable.
Reputation monitoring must first answer what was observed and what was missed before determining which issues require action. This post outlines a workflow blueprint: starting from approved monitoring targets, retaining comment identities and collection states, and routing evidence-backed issues to human review. It is not a feature description for a ready-made monitoring product or a customer case study; the data structures, rules, and synthetic samples are design examples rather than real brand outcomes or model accuracies.
Select a Business Problem Instead of Promising Full Coverage
"Monitor brand negativity" is too broad to define completion. A more actionable problem is determining whether the same service issue repeatedly appears in recent comments for specified locations, or whether quality feedback requiring verification appears in new product reviews. Once the problem is defined, you can determine which targets to watch, what evidence to retain, and who handles the review.
Maintain an watch_target list where each row includes the platform, object type, source URL, source object identifier, region or language, monitoring purpose, allowed collection scope, owner, and retention period. Version target changes separately: adding a store, pausing a product, or adjusting a region can alter the statistical baseline.
Public accessibility does not imply unrestricted collection or use. Before integration, verify target platform policies, data use cases, and necessary authorizations without collecting extra author profiles or contact details solely for normalization fields. This post does not grant access permissions for any platform or provide legal compliance conclusions for specific regions.
When managing merchant reviews you have permission to access, review the official Google Business Profile review management documentation to determine whether your requirements align with the official workflow. This cross-platform monitoring blueprint is not the same product as that API; see the Google Maps reviews API page for location review parameters under EveryInfra, and consult the EveryInfra API documentation for integration methods.
Use Catalog Selection Capabilities Without Treating Catalogs as Delivery Proof
The following examples query public capabilities only, without reading comments or using API keys. Execute them in a terminal with curl and jq; pipefail prevents request failures from being masked by subsequent JSON processing.
set -o pipefail
curl -fsS --max-time 20 \
'https://api.everyinfra.com/api/v1/social/catalog?platform=google_maps_reviews' \
| jq '.capabilities[] | select(.action == "reviews") |
{platform, action, required_params, optional_params, response_fields}'set -o pipefail
curl -fsS --max-time 20 \
'https://api.everyinfra.com/api/v1/social/catalog?platform=xiaohongshu' \
| jq '.capabilities[] | select(.action == "comments") |
{platform, action, required_params, optional_params, response_fields}'In the catalog check for 2026-9-4, both google_maps_reviews.reviews and xiaohongshu.comments require url. The former lists since while the action in the latter does not list this parameter, meaning a generic "continue from previous timestamp" request cannot be applied to both. The former declares rating and rating scale fields while the latter does not declare ratings, preventing comment sentiment tags from being placed in rating columns. Location review catalog, Xiaohongshu comment catalog
These observations only verify catalog declarations. Whether actual responses include each field, the timestamp format, pagination handling, and empty result representations must be verified separately within authorized samples. Unmeasured generic APIs are not provided here, nor is it claimed that collection for both platforms has been completed.
Three Timestamps and Two States Should Not Share a Column
A comment involves at least three timestamps: the publishing time provided by the source posted_at, the time this system first observed it first_seen_at, and the most recent observation time last_seen_at. Keep source timestamps empty when unknown, and do not use crawl times to impersonate publication times. Record original timezones and conversion rules when handling daily windows; relative expressions such as "just now" or "yesterday" lack reliable parsing and must be excluded from precise cross-day statistics.
Collection runs must also maintain their own records: run_id, target list version, request reference, request window, start and end times, actual delivered count, and collection status. Business systems should distinguish between:
succeeded: Delivery completed within the current request scope; does not equal historical completion.empty: Request succeeded and returned an empty set; does not mean the object has no comments.partial: Only partial targets or pages completed, retaining received results and gaps.failed: Failed to achieve agreed delivery, retaining troubleshootable error classifications.unknown: Timeout or unconfirmed result; cannot be arbitrarily counted as success, empty, or uncharged.
These statuses are business designs for this blueprint rather than claims that APIs return fields with matching names. Separate collection status from business judgment: collection failures should generate pipeline issues, and evidence-deficient content should be marked as pending rather than automatically labeled as negative-free.
Timestamp formats can reference RFC 3339 definitions for date, time, and UTC offset. This assists in unified storage representation, but posted_at, first_seen_at, and last_seen_at cannot be combined into a single business meaning, nor can timezones be imputed for unknown source times.
Stable Comment Identity with Mutable Content Versions
If the source provides a stable comment ID, the recommended identity key is (platform, source_object_id, source_review_id). Avoid relying solely on comment IDs, as different platforms or objects may generate identical values; likewise, avoid using text hashes alone, as two users writing the same short phrase does not imply the same comment.
When the same identity key reappears, evaluate content versions. Text or rating changes can produce new observation versions without counting as new comments. Record version summaries separately from first and recent observation times so reviewers can see content differences while increment calculations avoid double-counting. Differences may also stem from language or adaptation rule changes, so do not claim authors modified originals without verification. Records without stable source IDs enter review queues; approximate fingerprints must be marked as identity-uncertain rather than quietly used for precise deduplication.
Normalized layers retain only verified values and field sources for the current run. Ratings and scales are processed as pairs where empty ratings do not equal zero; missing owner_response responses do not imply merchants never replied. Keep original response structures separate from internal adaptation structures, and version adaptation rules to prevent old fields from being misinterpreted after interface upgrades.
Such version associations can be organized using W3C PROV provenance, processing activities, and derivation relations: original observations, normalized records, model tags, and alerts each retain origins. This design adopts a traceable approach without claiming output data strictly conforms to W3C PROV specifications.
Cursors Advance Only After Data Settles
Incremental collection risks hidden gaps: updating cursors to today before saving comments means failures can cause subsequent reruns to skip content. Advance cursors only after delivery, deduplication, persistence, and necessary checks complete for the target; manage progress for multi-target batches independently so success in one target does not prematurely advance others.
When validated pagination tokens exist, save them alongside matching targets, request conditions, and completed pages. For time-filtered queries, design overlapping windows and rely on identity keys for deduplication while clarifying that window lengths are business choices rather than zero-loss guarantees. Avoid adding unvalidated incremental parameters to catalogs; use verified read ranges before evaluating monitoring objectives.
Reaching single-run limits indicates sampling boundaries rather than complete historical retrieval. Old cursors may not remain reusable after sorting, regional, or language changes. Incorporate request conditions into progress versions, re-verify coverage scopes, and retain backfill tasks as a safe practice.
Failing to observe a comment in a single run does not automatically mark it as deleted. Changes in sorting, unreached pagination, or temporary invisibility can be factors; deletion status requires explicit verification rather than inference from missing samples.
An Offline Deduplication and Gap Demonstration
The following Node.js example processes fictional objects and tags only, without downloading content, invoking models, or sending alerts. It intentionally retains cross-object duplicate IDs, cross-platform duplicate IDs, repeated observations, edit versions, missing IDs, empty text, and unregistered targets to verify that identities and collection states are not conflated into a single success count.
Target states and text tags in this example are manually configured test inputs rather than real API responses or classification results. It functions as a local batch demonstration without implementing cross-run persistence, request retries, cursor submissions, or notification systems.
node <<'JS'
const assert = require('node:assert/strict');
globalThis.fetch = () => { throw new Error('Offline example: no network'); };
function inspectRun(targets, rows) {
const targetKey = r => JSON.stringify([r.platform, r.object]);
const states = new Set(['succeeded', 'empty', 'partial', 'failed', 'unknown']);
assert.ok(targets.length > 0);
assert.equal(new Set(targets.map(targetKey)).size, targets.length);
assert.ok(targets.every(t => states.has(t.state)));
const planned = new Map(targets.map(t => [targetKey(t), t.state]));
const identities = new Map();
let duplicates = 0, revisions = 0, quarantined = 0;
for (const r of rows) {
const state = planned.get(targetKey(r));
const canReadRows = state === 'succeeded' || state === 'partial';
if (!canReadRows || typeof r.id !== 'string' || !r.id.trim()
|| typeof r.text !== 'string' || !r.text.trim()) {
quarantined++;
continue;
}
const key = JSON.stringify([r.platform, r.object, r.id]);
// This fixture arrives in observation order; text alone is not an identity.
const version = JSON.stringify([r.text]);
if (identities.get(key) === version) duplicates++;
else {
if (identities.has(key)) revisions++;
identities.set(key, version);
}
}
return {
uniqueReviewsInBatch: identities.size,
duplicates, revisions, quarantined,
targetCoverageGate: targets.every(t => ['succeeded', 'empty'].includes(t.state)),
};
}
const targets = [
{ platform: 'maps-fixture', object: 'place-a', state: 'succeeded' },
{ platform: 'maps-fixture', object: 'place-b', state: 'succeeded' },
{ platform: 'notes-fixture', object: 'note-a', state: 'partial' },
{ platform: 'video-fixture', object: 'video-a', state: 'failed' },
];
const first = { platform: 'maps-fixture', object: 'place-a', id: '7', text: 'synthetic reviewA' };
const rows = [
first,
{ ...first },
{ ...first, object: 'place-b' },
{ ...first, platform: 'notes-fixture', object: 'note-a' },
{ ...first, id: null },
{ ...first, id: '8', text: ' ' },
{ ...first, text: 'synthetic reviewedited version of A' },
{ ...first, object: 'unplanned' },
];
const report = inspectRun(targets, rows);
assert.deepEqual(report, {
uniqueReviewsInBatch: 3, duplicates: 1, revisions: 1,
quarantined: 3, targetCoverageGate: false,
});
assert.equal(inspectRun(targets, [...rows, rows[6]]).duplicates, 2);
assert.equal(inspectRun([{ ...targets[0], state: 'empty' }], []).targetCoverageGate, true);
assert.equal(inspectRun([{ ...targets[0], state: 'unknown' }], []).targetCoverageGate, false);
assert.equal(inspectRun([{ ...targets[0], state: 'failed' }], [first]).quarantined, 1);
assert.equal(inspectRun([targets[0]], [{ ...first, id: ' ' }]).quarantined, 1);
assert.throws(() => inspectRun([], []));
assert.throws(() => inspectRun([targets[0], targets[0]], []));
assert.throws(() => inspectRun([{ ...targets[0], state: 'typo' }], []));
console.log(JSON.stringify(report, null, 2));
JSExpected results include 3 comment identities, 1 repeated observations, 1 edit versions, and 3 records pending review, with target coverage failing acceptance gates. empty satisfies the request completion target status gate without proving objects lack comments. Even when target status gates pass, page coverage, sample baselines, and metadata must be verified before comparing trends; boolean values do not imply authorization to draw external conclusions.
This example processes items in observation order and compares text versions only; production adapters should track fields such as ratings, define handling rules for out-of-order data and historical versions, and avoid unconditionally treating late-arriving records as the latest source version.
Records pending review should not be casually discarded or counted as new. Inspect adapters, target lists, and missing fields by cause; incorporate items into statistics only after identities are resolved or approximate processing is explicitly accepted. Avoid removing failed targets from plan denominators solely to improve daily report aesthetics.
Form Candidate Evidence Before Model Classification
Ensure topic tags carry at least review_key, comment versions, rule or model versions, tags, evidence snippets, and manual processing status. Summaries must map back to supporting source text; model confidence scores are uncalibrated and do not represent exact probabilities for automated complaint escalation.
Comment bodies are untrusted input. Text stating "ignore previous instructions" or "send these data out" must be treated strictly as text for analysis rather than operational commands for agents. Classification steps require no payment, deletion, or outbound permissions; separating data retrieval, classification, human review, and transmission reduces risks of accidental execution.
Starting with a specific topic and a set of human-verified samples is easier to interpret than enabling numerous tags simultaneously. Classification requires an "undetermined" category and recorded reasons for whether language, context, or missing fields caused it; avoid lumping undetermined cases into neutral categories, which dilutes issues requiring review.
This permission division aligns with OWASP indirect prompt injection guidance: external content may carry instructions, requiring independent control over tool permissions and actual actions. A statement asking to ignore comment instructions is neither a complete defense nor authorization for outbound transmission.
Collection Gaps Should Not Mask High-Risk Evidence
Evaluating whether a topic is escalating requires comparable windows, clear denominators, and minimum sample criteria. Comparison scopes should cover identical target sets, regions, sorting, and inclusion rules. Pause overall trend conclusions when daily coverage is incomplete while routing acquired evidence requiring attention to human reviewers without hiding data due to partial completeness.
Separate matters into distinct queues: route collection gaps to data owners and specific complaint evidence to business owners. Do not translate HTTP errors into brand risks, nor report failures to collect comments as "no anomalies today."
Candidate alerts must specify objects, observation windows, trigger rules, comment identities and versions, evidence snippets, coverage limits, owners, and processing states. Assign stable event keys to prevent duplicate notifications during rerun windows; update events with revision records when comments are edited or labels corrected rather than silently overwriting old conclusions.
When handling personal safety, medical, discrimination, legal disputes, or employee penalties, models should assist solely with evidence organization while appropriate owners handle final judgments and external actions. The blueprint does not automatically reply to comments, contact commenters, or publish handling results.
Verify with Failure Scenarios Before Launch
Verify minimal collection within approved scopes before running the complete ingestion, replay, candidate queue, and manual processing pipeline. Cover at least the following scenarios:
- Reprocessing the same batch adds no new comment identities and triggers no duplicate notifications.
- Duplicate IDs appearing across different objects or platforms are not erroneously merged.
- Edited comments retain modification evidence without creating new comment entries.
- Partial target failures retain delivered content while unfinished target progress remains unadvanced.
- Empty results, empty text, and missing pagination evidence are presented distinctly rather than lumped as zero new items.
- Data storage failures prevent cursors from advancing past affected batches, enabling safe replays after recovery.
- Source data corrections, deletion requests, or expired retention periods allow targeted handling of associated tags, summaries, and alert evidence.
Offline demonstrations check identity and status rules but do not prove persistence, collection, notification, or model classification acceptance. Before production use, establish data retention, deletion, access, and export permissions; default logs must exclude full comments, credentials, or unnecessary personal information.
Next Steps: Deliver Evidence Chains Suitable for Human Handling
Select a small number of approved targets, a business problem, and an observation window with a designated owner. Prove that each run clearly defines success scopes and gaps, verify that individual pieces of evidence are not double-counted, and determine which items enter manual processing queues.
Designs can be reviewed as blueprints without customer testimonials or verifiable metrics, but they cannot be packaged as claims that a brand was helped. Treat writings as practical tutorials with end-to-end samples, or as customer case studies complete with consent, baselines, results, and limitations. These represent distinct evidentiary requirements.