How to Find a Customer's Item Pricing Level in NetSuite
Learn how to identify and extract custom pricing levels in NetSuite Analytics Warehouse for accurate customer profitability reports.

On this page
Why the Standard "Price Level" Field Misses Custom Pricing
You're staring at a customer record in NetSuite Analytics Warehouse (NSAW), also called the Analytics Data Warehouse or ADW, and the Price Level column shows the assigned price level, like "Wholesale" or "Retail." But finance prices customer-specific items under a Custom price level, and that bucket is nowhere in the standard dimension. Pricing rows show up in DW_NS_X_CUSTOMER_ITEM_PRICING with Customer ID, Item, and Price, but the Pricing Level name is missing. This is the exact gap that breaks customer profitability and custom-pricing reports.
The reason is structural. NetSuite stores custom price levels as transaction-time overrides on the item record, not as a standalone dimensional attribute on the customer. NSAW exposes the customer's assigned price level (the default tier) but not the per-item custom override bucket. You have to derive the pricing level from the source data and stitch it into your dataset.
The standard ADW customer dimension shows assigned price levels only. Custom per-item pricing lives in a separate pricing fact table without a level-name column.
Step 1: Build a Saved Search That Surfaces the Pricing Level Name
Start in NetSuite itself (not NSAW) to confirm what NetSuite tracks. Go to Reports > New Search and click Pricing on the Search type page. Check Use Advanced Search.
A pricing search lets you set up an item search to generate a price list, such as displaying the price of items at a certain price level for all items on that level. On the Criteria subtab > Standard subtab:
- Filter: Assigned Price Level → Yes
- Filter: Customer → select the customer record (or leave blank for all)
On the Results tab, add these columns:
| Column | Source Field |
|---|---|
| Customer | Name |
| Item | Name |
| Item Price | Rate |
| Price Level | Price Level (Item Pricing Schedule) |
| Quantity | Minimum Quantity |
The "Price Level" result column on the pricing search is the key. It returns the name of the price level tied to each item pricing record, including the implicit "Custom" bucket NetSuite creates when you override a price directly on a transaction. If a row shows up here with Price Level populated as "Custom," you've confirmed NetSuite is tracking the override, it's just not surfaced as a dimension in NSAW.
Save the search. Export it as CSV to cross-reference against your ADW extracts while you build the dataset.
Step 2: Map the NSAW Table Structure
In NSAW, navigate to the Data Warehouse interface and locate the customer item pricing dataset. The relevant table is DW_NS_X_CUSTOMER_ITEM_PRICING under the OAX_User schema. The columns you'll see:
| Column | Description |
|---|---|
| Customer ID (NS) | Internal NetSuite customer ID |
| Item ID (NS) | Internal NetSuite item ID |
| Price | The negotiated rate for that customer-item pair |
| Currency | Transaction currency |
Notice what's absent: there's no Pricing Level Name or Price Level NS column. This is the gap you're working around. Every row in this table represents a custom override, but the level name has to be enriched from the NetSuite source.
The
DW_NS_X_CUSTOMER_ITEM_PRICINGtable stores the override rate but not the level name, enrichment is required.
Step 3: Enrich the NSAW Dataset via a Custom Field Join
You have two paths to attach the pricing level name.
Path A, SuiteAnalytics Workbook enrichment (no SQL):
Open a Workbook in NSAW against DW_NS_X_CUSTOMER_ITEM_PRICING. Because the table itself doesn't carry the level name, the practical move is to load the saved-search export from Step 1 as a separate dataset, join on Customer ID + Item ID, and pull Price Level into the pricing fact.
The join key is the combination of Customer ID (NS) and Item ID (NS) in the ADW table against the Customer (internal ID) and Item (internal ID) columns in your exported saved search.
Path B, Custom NetSuite data source for ADW:
If your team owns the ADW pipeline, create a SuiteQL-driven custom dataset that includes the level name directly from the source. Price levels themselves are surfaced under Setup > Accounting > Accounting Lists > New > Price Level in NetSuite, and the underlying record carries the internal ID pricelevel. The query joins the item pricing schedule to its level name:
SELECT
cipr.customer AS customer_id,
cipr.item AS item_id,
cipr.price AS override_price,
cipr.currency AS currency_id,
cipl.name AS pricing_level_name
FROM customrecord_customer_item_pricing cipr
LEFT JOIN customrecord_item_pricing_schedule cipl
ON cipr.pricing_schedule = cipl.id
WHERE cipr.isinactive = 'F'The exact table names (customrecord_customer_item_pricing, customrecord_item_pricing_schedule) and join keys depend on how your account's custom records are configured. Verify these in your environment under Customization > Lists, Records, & Fields > Record Types before deploying the query.
Step 4: Build the Custom Report in NSAW
With the enriched dataset, the report build is straightforward. In a Workbook:
- Dataset:
DW_NS_X_CUSTOMER_ITEM_PRICING(enriched with Pricing Level Name). - Rows: Customer Name, Item Name.
- Column: Pricing Level Name (from the joined source).
- Measure: Sum of Price (or Average Price, depending on whether you sell at multiple quantities).
Add a filter for Pricing Level Name = "Custom" if you want only the per-item override rows. Add a filter for Pricing Level Name not equal to the customer's default assigned level to find pricing exceptions, the lines that deviate from the baseline tier.
For a profitability roll-up, drag Price and the standard Cost field onto the same pivot to compute margin by pricing level.
Edge Cases That Trip People Up
Quantity-based pricing disappears. If you set up pricing tiers at quantities 0, 10, 100, and 1000, the DW_NS_X_CUSTOMER_ITEM_PRICING table may only carry the base (quantity 0) row. NetSuite Connector can sync the price from any of these quantity levels, but only when quantity-based pricing is enabled in both NetSuite and the connector. Don't create quantity-based price mappings in NetSuite Connector if the feature isn't enabled in NetSuite, or the mapping will fail. Validate the row count against the saved-search export before you trust the totals.
Inactive pricing rows pollute the dataset. Customer-specific pricing rows can be deactivated without deletion. Filter on isinactive = 'F' (or the equivalent ADW flag) to exclude them; otherwise historical reports will include pricing the customer hasn't been on for months.
Currency mismatches. A customer assigned to a foreign-currency price level will show the rate in that currency. If you're rolling up margin across currencies, apply the exchange rate at the document level, not the pricing record level, the pricing record has no transaction date attached.
"Custom" vs. named custom levels. When you override a price directly on a sales order by selecting Custom in the Price Levels field and entering a rate, NetSuite doesn't always tag that row with a named pricing schedule. Per the Item Record Management guidance, selecting Custom in the Price Levels field on transactions creates an inline override rather than a stored schedule row. The Pricing Level Name will appear as Custom (or blank) rather than a named level like "VIP 2024." Account for this in your report filters, or create named price levels for every override you care about reporting on.
Once the dataset includes the pricing level name and you've filtered for active, non-base-tier rows, the customer profitability picture is finally complete, and the spreadsheet reconciliation against the saved search should tie out to the cent.


