SERP API positions should be stored as typed, scoped measurements, not as one universal rank. In Google SERP data, use organic position for movement among organic listings, absolute order for a provider's documented mixed sequence, group or child position inside a feature, and reference order for sources inside an AI surface. If the response cannot identify the result type and the scope of its position, do not normalize the number into rank history.
That rule prevents a common reporting error: an ad, local pack, featured snippet, AI Overview, and organic result can all be described as “position 1” while referring to different sequences. The values are not contradictory. They answer different questions. A safe schema preserves those questions instead of hiding them behind a generic position field.
Mixed-result handling is therefore a data-contract decision before it is a calculation. The contract must state what is being ordered, which elements enter the count, whether the item is a parent block or a nested child, and which query, market, location, language, device, result depth, page region, and collection time produced the observation.
The Short Answer: Every Position Needs a Type and Scope
A position value is safe only when its label explains the sequence it belongs to. Six scopes cover the main cases in a mixed SERP response:
| Position scope | Question it answers | Appropriate use | Do not use it as |
|---|---|---|---|
| Organic position | Where is this web result among organic listings? | Conventional organic rank tracking. | The first visible or first counted page element. |
| Absolute order | Where is this top-level element among the elements counted by this provider and endpoint? | Reconstructing a documented mixed sequence. | A universal Google rank or pixel position. |
| Group position | Where is this item among items of the same documented type? | Comparing organic with organic, ads with ads, or another consistent type with itself. | A comparison across different result types. |
| Parent-block position | Where does the local pack, carousel, People Also Ask (PAA) block, or other feature group occur? | Monitoring feature placement in the provider's top-level model. | The position of every item nested inside the block. |
| Child position | Where is this item inside its parent feature? | Ordering businesses, products, cards, questions, or sitelinks within one group. | Organic or absolute rank. |
| Reference order | Where does a source appear in an AI answer's citations, cards, or references? | Monitoring source presentation inside the same AI surface. | Organic rank, quality score, or a stable citation rank. |
This is why “position 1” should never stand alone in a storage model or dashboard. Prefer labels such as organic_position: 1, ad_group_position: 1, local_child_position: 1, or reference_order: 1. If the provider supplies an unexplained position: 1, retain it as a raw value but set the normalized position to unknown until the containing object and endpoint contract establish its meaning.
Decision rule: if a reader cannot tell which sequence was counted from the field name and its metadata, the value is not ready for comparison, alerts, or reporting.
Choose the Position Field Before You Normalize the Response
SERP API providers commonly expose one of two response patterns. A mixed-item response may return typed elements in one array with fields such as rank_group and rank_absolute. A type-specific response may keep organic_results, ads, local results, and answer features in separate objects or arrays, with position meaningful only inside its container.
For example, DataForSEO documents rank_group as order among elements with the same type and rank_absolute as order among the SERP elements its endpoint counts. It also documents cases where right-side desktop elements use a separate absolute sequence. SerpApi, by contrast, documents position inside its organic_results array while returning ads, local results, answer boxes, and other features in separate structures. Renaming all three provider fields to position would erase the distinction that the integration needs most.
Normalize the semantics, not the spelling:
| Result type | Valid position fields when documented | Context required | Unsafe interpretation |
|---|---|---|---|
| Organic result | Organic position; group position for type organic; absolute order when supplied |
Result type, page or depth, device, market, provider endpoint | Absolute order reported as organic rank. |
| Paid ad | Ad-group position, block placement, absolute order | Paid label, top or bottom block, device, endpoint | Paid placement reported as organic visibility. |
| Local pack | Parent-block or absolute order for the pack | Location, device, page region, parent identity | Pack placement assigned to each business. |
| Local business | Child or local-group position | parent_id, place identity, location, device |
Organic position based on the business website URL. |
| Featured snippet | Feature occurrence and absolute order when defined | Feature type, source URL, occurrence identity, organic relationship | Automatic organic position zero or a permanent best rank. |
| PAA, shopping, video, or carousel item | Child or group order | Parent feature, item type, child identity | Independent top-level or organic rank. |
| AI Overview | Surface presence and top-level order when the provider documents it | Search surface, feature status, query scope, provider contract | Organic rank for the answer or its sources. |
| AI source or card | Reference, card, or citation order | Parent answer observation, source URL, order type | Ranking strength or conventional SERP position. |
Consider a hypothetical provider that counts each top-level block once. This is an example of one possible contract, not a universal Google sequence:
| Absolute order | Top-level result type | Group position | Organic position |
|---|---|---|---|
| 1 | Top ad | 1 among ads | — |
| 2 | AI Overview | 1 among AI Overview blocks | — |
| 3 | Organic result A | 1 among organic results | 1 |
| 4 | Local pack parent | 1 among local packs | — |
| 5 | Organic result B | 2 among organic results | 2 |
The first organic result is simultaneously organic position 1 and absolute order 3. The local pack is absolute order 4, but its first, second, and third businesses are children of that one parent block; they are not automatically absolute orders 4, 5, and 6. Another provider may return all of these features in separate arrays and expose no absolute order at all. In that schema, trying to reconstruct one from array order would create unsupported data.
A normalized internal record should preserve both the provider fields and the interpretation applied by the integration. The internal field names and mapper version below are illustrative:
{
"result_type": "organic",
"provider_position": null,
"provider_rank_group": 1,
"provider_rank_absolute": 3,
"position_kind": "organic",
"normalized_position": 1,
"parent_result_id": null,
"page_region": "main",
"mapper_version": "position-mapping-v1"
}
provider_rank_absolute remains available for layout analysis, but it does not overwrite normalized_position for an organic rank report. The mapper version is equally important: when a provider starts recognizing a new feature, absolute values can change even if the visible result order did not.
Practical takeaway: decide the question the number must answer, verify the provider's counting contract, and only then populate a normalized field.
Organic Results and Ads Belong in Separate Ranking Lanes
Organic position should answer one narrow question: where did a web result appear among the organic listings collected under the same request scope? Ads should answer a paid-placement question. A URL, title, snippet, and integer position do not make the two result types interchangeable.
Top ads can appear before the first organic result. Under a documented mixed counter, they may increase that result's absolute-order number. They do not consume its organic position. A page can therefore remain organic position 1 while moving from absolute order 1 to absolute order 3 because two counted paid elements appeared before it.
Bottom ads need the same separation. Do not assume that an ad_position field uses one continuous sequence across top and bottom blocks. A provider may number all ads together, number each block independently, or expose only array order. Store the block placement, such as top or bottom, with the ad-group position so the value remains explainable.
The same domain may also appear in both a paid placement and an organic result. Domain-level deduplication would erase one occurrence and make it impossible to explain whether visibility was paid, organic, or both. Preserve each typed occurrence, even when the landing URLs match after normalization.
A dashboard should use explicit labels:
| Label | Supported meaning |
|---|---|
| Organic position | Order among documented organic results. |
| Paid position | Order inside a documented paid block or ad sequence. |
| Mixed absolute order | Order among top-level elements counted by the provider. |
| Ads before target | Count of documented paid elements preceding the matched target under the same observation. |
Do not label rank_absolute as “Google position.” It is a provider-scoped ordering field, not proof of pixel depth, above-the-fold status, click potential, or the physical space occupied by an ad.
Decision rule: use organic position for organic movement and paid placement for ad movement. Use absolute order only to describe a documented mixed sequence, never to merge the two histories.
Local Packs and Grouped Features Need Parent and Child Positions
A local pack has at least two ordering layers: the pack's placement as a top-level SERP feature and the businesses' order inside the pack. The parent can have an absolute or feature-block position while each business has a local child or group position. Those values belong in separate records connected by parent_result_id.
| Local layer | Position to keep | Required identity and scope | Invalid shortcut |
|---|---|---|---|
| Local pack parent | Feature-block or absolute order when documented | Query, location, device, page region, collection time | Copy the parent position to every business. |
| Business child | Local group or child position | Parent ID, business or place ID when available, location, device | Treat the website URL as an organic ranking. |
| Business website occurrence | Its own typed occurrence | URL, parent business, occurrence type | Deduplicate it against an organic result from the same domain. |
Location is not optional context for local positions. A business at child position 2 for one city, coordinate set, or device cannot be compared directly with child position 1 under a different local scope. If location is missing or inherited from an unknown provider default, keep the observation for inspection but block local rank history.
The same parent-child rule applies to other grouped features:
- A shopping block has a parent placement and product children with product or offer identity.
- A video carousel has a parent placement and card order; a video card is not an ordinary organic result merely because it links to a URL.
- A People Also Ask block contains questions and sometimes exposed sources. Question order and source occurrence remain under the PAA parent.
- An organic result can contain sitelinks. The sitelinks inherit the parent context and do not become additional organic rankings.
- A right-rail panel needs region metadata. Its order may be separate from the main column, so it should not be inserted into the main sequence unless the provider explicitly defines that behavior.
These differences are why mixed features often need separate SERP feature data models. A flattened export is acceptable for a downstream report only if every row retains enough information to reconstruct its parent, result type, position scope, and page region.
Red flag: if flattening a response turns one local pack with three businesses into three independent top-level ranks, the model has changed the evidence rather than normalized it.
Featured Snippets Can Create Two Typed Occurrences for One URL
An ordinary result snippet is descriptive text attached to an organic result; it does not receive a position of its own. A featured snippet is different. It is a typed SERP feature that may identify a source URL and may occupy a documented position in the provider's response.
Depending on the observed SERP and the provider's model, the same URL can appear as a featured-snippet source and as an organic result. The safe representation is two occurrences:
| Occurrence | Fields to preserve | Position meaning |
|---|---|---|
| Featured-snippet occurrence | Feature type, source URL, visible answer text when supplied, feature or absolute order, observation ID | Placement of the feature under the provider's contract. |
| Organic occurrence | Organic type, URL, title, ordinary snippet, organic position, absolute order when supplied | Placement among organic listings and optionally the mixed sequence. |
Do not deduplicate these rows solely because their URLs match. Doing so can produce either of two errors: the feature occurrence disappears and the tool underreports feature visibility, or the organic occurrence disappears and the tool overwrites organic history with a feature position.
A “best position” metric can be created only after the product defines what it means. A cross-surface presence score, for example, may deliberately count any typed occurrence. It still should not write that aggregate back into organic_position. Keep the raw occurrences and compute the rollup as a separate, labeled metric.
The same caution applies to a source exposed inside People Also Ask. Its source URL is evidence of a PAA occurrence, not an automatic organic result and not proof that the page holds the same organic position.
Decision rule: identity matching may connect occurrences, but it must not erase result type. Keep feature placement and organic position in separate lanes even when one URL owns both.
AI Overviews and AI Surfaces Need Reference Order, Not Organic Rank
AI Overviews are answer-surface observations. When present, they can contain generated answer sections, source cards, citations, links, videos, products, or local details. These objects do not form one conventional organic ranking list.
Separate three layers when the provider exposes them:
- Surface status. Record
present,absent,unavailable,partial,blocked, ornot_checked. An empty object is not enough because absence can mean the feature did not trigger, collection failed, or parsing was incomplete. - Top-level feature order. Store an absolute or parent-block order only if the provider documents where the AI Overview enters its mixed sequence.
- Reference order. Store citation, card, link, or source order exactly as the provider defines it. If no order is documented, use null rather than deriving a rank from JSON array order.
A source shown first in an AI Overview is not organic position 1. It is also not necessarily the “best” or most authoritative source. The supported claim is narrower: the source appeared at a particular documented reference order in one answer-surface observation.
If the same URL also appears in the organic results, retain both occurrences and connect them through an overlap record or query-time analysis. That supports statements such as “this URL appeared organically and as an AI reference in the same scoped observation.” It does not justify merging the two positions.
AI Mode and similar conversational experiences need a separate search_surface value. They may use follow-up context and multiple related searches, so their source sequence should not be inserted into a classic web SERP counter. Compare AI Mode observations only when the surface, query or conversation policy, market, language, device, collection method, and provider schema are equivalent.
The automation boundary is especially important here. AI-surface visibility can support monitoring, source extraction, or overlap analysis. It should not trigger edits to an owned page unless the workflow has a clear target_url and page-level evidence. A domain match alone can select the wrong page, and an AI reference alone does not prove which page change would be appropriate.
Practical takeaway: record AI presence and reference order as their own evidence types. Use null when order is not documented, and require a specific target_url before AI-surface observations can influence owned-page automation.
Red Flags That Should Stop Mixed-Position Comparison
Mixed SERP data often looks complete because every row has a URL and an integer. Stop or downgrade the comparison when any of these conditions appears:
| Red flag | Why it breaks the comparison | Safer action |
|---|---|---|
position exists but result_type is missing |
The number could belong to organic, paid, local, a child group, or a reference list. | Preserve the raw row and set normalized position to unknown. |
| The provider does not document what absolute order counts | New or omitted feature types can silently change the sequence. | Do not use the field in reporting or alerts. |
| Parent IDs are lost during flattening | Child items can be mistaken for top-level results. | Rebuild the model before calculating movement. |
| Main-column and right-rail items share a forced sequence | Parallel page regions may not have a supported order. | Store page_region and compare within the documented region. |
| A local result lacks location or device context | The observation cannot support a stable local comparison. | Downgrade it to exploratory evidence or recollect with explicit scope. |
| AI references are mapped to organic position | Reference order and organic rank answer different questions. | Keep a separate AI visibility series. |
| The same URL is deduplicated across result types | Feature ownership, paid visibility, and organic visibility disappear into one row. | Preserve typed occurrences and link them without merging. |
| Provider, endpoint, parser, or mapper version changed | A schema change can look like a ranking change. | Quarantine the delta until raw responses and mappings are reviewed. |
| Result depth or requested page changed | A missing result may simply be outside the collected window. | Compare only equivalent depth and pagination scope. |
An automation has no explicit target_url |
A domain-level match can act on the wrong owned page. | Block page-level actions until the target is defined and extracted. |
Another warning sign is a history table containing only keyword, url, and position. It cannot show whether the row was organic or paid, whether it came from a local child, whether the provider changed its parser, or whether the query ran on a different device. The table may be compact, but it is not decision-grade evidence.
Decision rule: an unknown scope is not equivalent to any known scope. Do not fill missing semantics with assumptions merely to keep a chart continuous.
Use This Validation Checklist Before Comparing Positions
Apply this sequence to validate SERP API data before a mixed response updates rank history, dashboards, alerts, or AI workflows.
- Name the decision. Decide whether the workflow needs organic movement, paid placement, feature layout, local child order, grouped-item order, AI-reference visibility, or cross-surface presence. One generic rank cannot support all of them.
- Verify the result type. Confirm that each item is explicitly organic, paid, local, featured, grouped, nested, or part of an AI surface. Unknown types should remain unknown until mapped.
- Assign the position scope. Map the provider field to
organic,absolute,group,parent,child,reference, ornot_applicable. Do not infer the scope from the wordpositionalone. - Preserve hierarchy and region. Store
parent_result_id, child identity, andpage_region. Keep sitelinks under organic parents, businesses under local packs, cards under carousels, and sources under answer surfaces. - Attach the complete request key. Preserve exact query, country or market, language, location when relevant, device, search surface, requested page or result depth, filters, and collection time.
- Keep raw and normalized fields. Store the provider's original position values, then add the normalized meaning separately. Record provider, endpoint, schema version, parser version, and mapper version.
- Check comparison equivalence. Before you compare repeated SERP API requests, confirm that the records use the same result type, position scope, parent policy, request key, target-matching rule, and compatible schema behavior.
- Classify the delta before acting. Label it as organic movement, paid movement, feature-layout change, child-order change, AI-reference change, result-type change, or incomparable scope drift.
- Apply the automation gate. Reporting may need only a validated observation. Any recommendation or edit for an owned page also needs a clear
target_urland page-level evidence.
The checklist should end in one of four outcomes:
| Outcome | Use when | Next action |
|---|---|---|
| Accept | Type, scope, hierarchy, request key, and schema are comparable. | Update the matching typed history only. |
| Accept for a narrower use | Some context is missing, but the observation supports feature presence or exploration. | Keep it out of rank alerts and page automation. |
| Quarantine | Parser, schema, parent mapping, or feature handling may explain the delta. | Inspect raw evidence or replay the mapping before publishing a change. |
| Reject | Position scope or result identity cannot be established. | Do not normalize or compare the value. |
The central implementation choice is straightforward: preserve several precise positions instead of manufacturing one convenient number. Organic results, ads, local packs, featured snippets, grouped features, and AI sources can all be useful in the same response. They become misleading only when the data model pretends they belong to the same ranking sequence.
Want more SEO data?
Get started with seodataforai →